Home » c# » .net – How to correctly read the method signature of the .Any function in C#

.net – How to correctly read the method signature of the .Any function in C#

Posted by: admin February 21, 2020 Leave a comment

Questions:

I really enjoy using the aggregate functions that C# provides such as .Any(), but I struggle to understand what my options are just looking from the method signature:

enter image description here

Can someone help me better understand the meanings of (Func predicate)? I know that I normally use a lamda fucntion here. But, how that translates back into whatever Func is, I don’t understand.

How to&Answers:
(extension) bool IEnumerable<string>.Any<string>(Func<string, bool> predicate)(+ 1 overload)
Determines whether any element of a sequence satisfies a condition.

Exceptions:
  ArgumentNullException

Means:

  • You can call this as an extension method.
  • On an IEnumerable<string>, that is something you can iterate on that gives you string. string is type that holds text.
  • The name of the method is Any
  • It has a type argument, which is set to string. You probably can call this on a IEnumerable<T> where T is something other than string.
  • It takes a Func<string, bool> predicate, that is a delegate to a function that takes a string as input parameter and returns a bool.
  • There is another overload of the method, which takes different arguments.
  • The method documentation says it “Determines whether any element of a sequence satisfies a condition.” We can presume it goes over the IEnumerable<string> calls the Func<string, bool> passing the string from the IEnumerable<string> passing each value, and returns whether or not it got true for any one of them.
  • The method is documented to throw an ArgumentNullException, presumubly if you pass a null.

If we look online for it, we find in the official documentation Enumerable.Any. There we can see the other overload and also some examples.

Here is one:

Pet[] pets =
        { new Pet { Name="Barley", Age=8, Vaccinated=true },
          new Pet { Name="Boots", Age=4, Vaccinated=false },
          new Pet { Name="Whiskers", Age=1, Vaccinated=false } };

    // Determine whether any pets over age 1 are also unvaccinated.
    bool unvaccinated =
        pets.Any(p => p.Age > 1 && p.Vaccinated == false);

We see an array of Pet, and we call Any on it. Thus, in this case the type argument is Pet instead of string, given that an array of Pet is a thing over which you can iterate and it gives you elements of type Pet… I’m saying that an array of Pet is an IEnumerable<Pet>… and thus we are calling Any<Pet>.

We observe that the parameter is a lambda expression: p => p.Age > 1 && p.Vaccinated == false

This lambda represents an anonymous function that takes an argument p. Since we know that we are using Any<Pet>, and we know that Any<Pet> wants a delegate to a function that takes a Pet and returns bool, we know that p is a Pet.

The anonymous function takes the Pet p compares the property Age with 1 and the property Vaccinated with false, and return true if Age is greater than 1 and Vaccinated is false.

Looking at the values in the array, we can see that the second item (the one of Name "Boots") has Age greater than 1 and Vaccinated is false. Thus, the anonymous function should return true for that Pet.

And given that Any return true if the predicate (the anonymous funciton) was true for any of the elements, we expect Any to return true in this case. The description of the example and expected output in the official documentation confirms this.

If we still have the doubt, we can, of course, try running the code: code on SharpLab. The expected output is “There are unvaccinated animals over age one.”.


If you want to go one step deeper, you can search the reference implementation of Enumerable.Any.

If you know where to look, you can get the .NET Core source for Enumerable.Any, Not guaranteed to stay there, refectoring could put it somewhere else.

You may also be interested in the documentation about extension methods.


See also What is Func, how and when is it used.

###

But, how that translates back into whatever Func is?

Well, first we need to know what Func is.

Let’s see how Func is declared:

public delegate TResult Func<in T,out TResult>(T arg);

We can see that Func is a delegate. If you don’t know what a delegate is, there are wonder pages out there that tell you about them: 1, 2, 3.

How is related to the lambda expression you pass in?

The declaration says that Func is a delegate that takes a parameter of type T, and returns a TResult. From the signature of Any, we can see that T is string while TResult is bool in this particular case.

This means that you can convert a lambda expression, (or a method group,) that takes a string as a parameter and returns bool to an instance of Func<string, bool>.

Let’s say you call Any like this:

something.Any(x => x.Length > 10)

From the parameter type, the compiler infers that the lambda expression must take a string, so the type of x must be string. And the lambda expression must also return a bool, which it does, so we’re good! The lambda expression is converted to an instance of Func<string, bool>.