1

What is the name of the "construction" at line 3 in which Contains is invoked, but without parentheses? Is it some kind of syntactic sugar?

string current = "02";
string[] list = {"00", "01", "02", "03", "10"};
if (list.Any(current.Contains)) {
  // logic
}

I just can not figure out why and how it works nor what it is called?

Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
Techek
  • 465
  • 5
  • 14
  • 6
    It is method group. And it is not invoked, but converted to compatible delegate type. https://github.com/dotnet/csharplang/blob/master/spec/conversions.md#method-group-conversions – user4003407 Mar 27 '19 at 15:25
  • You're not calling `current.Contains`. You're passing a reference to `current.Contains`. It is then called, via that reference, by `list.Any()` -- or perhaps by some other method that `list.Any()` passes it to. A very helpful exercise would be for you to write your own equivalent of `List.Any()`. – 15ee8f99-57ff-4f92-890c-b56153 Mar 27 '19 at 15:30
  • There are no parantheses, as you are there not executing contains, but "passing" the method reference to the Any-function. – Malior Mar 27 '19 at 15:31

2 Answers2

3

You may recall that you can subscribe to events by doing this:

something.SomeEvent += SomeHandler;

That's syntactic sugar for:

something.SomeEvent += new EventHandler(SomeHandler);

This creates a new EventHandler instance (EventHandler is a delegate type), which uses the method SomeHandler.

Something similar is going on here.

list.Any takes a Func<T, bool>, which is a delegate type. Therefore you need to pass it an instance of Func<T, bool>.

When you write:

list.Any(x => current.Contains(x))

the compiler creates a new method (which takes a string, returns a bool, and just calls current.Contains), and does something like this:

list.Any(new Func<string, bool>(GeneratedMethod))

Now, you can also create that Func<string, bool> delegate instance from an explicit method yourself, just as in the EventHandler example:

list.Any(new Func<string, bool>(current.Contains))

Or, you can leave off the new Func<string, bool> and the compiler will generate it for you, again just as in the earlier example:

list.Any(current.Contains)
canton7
  • 37,633
  • 3
  • 64
  • 77
2

The list.Any() function takes a predicate function as the first parameter. Normally this is an inline lambda function like list.Any(s => s == "01"), but of cause you can pass in a properly defined function like in your example.

s => s == "01" and current.Contains have the same signature. They both take a string as the only input parameter and return a boolean. Therefore they can both be used as the predicate in the list.Any() function.

For more information about method groups check out THIS LINK and for information about Lambda function see here

Simon
  • 1,244
  • 8
  • 21