4

I was reading this answer about how to search a string for any of the strings contained in an array. The solution is beautifully concise:

if(stringArray.Any(stringToCheck.Contains))

My question is, how is it that the Contains() term doesn't require an explicit parameter? I would have written the above as:

if(stringArray.Any(s => stringToCheck.Contains(s)))

What are the rules for using this shortened version?

Community
  • 1
  • 1
Geoff
  • 8,551
  • 1
  • 43
  • 50
  • furthermore, I believe this is called point-free style in functional programming - as you don't need to specify the arguments explicitly – rla4 Jun 18 '14 at 15:35
  • 2
    To be honest, does not look like dupplicate, at least of the question marked as such. Method group has nothing to do with actual question posted here. – Tigran Jun 18 '14 at 15:37
  • @Ahmad, your duplicate choice is not very good. – Kirk Woll Jun 18 '14 at 15:38
  • 1
    @Tigran have you read the question? how is this not relevant with method group? – Selman Genç Jun 18 '14 at 15:38
  • 1
    @Selman22: yes, and that's why it's not a dupplicate. It's not asking about method group desription, but why is the provided code works ? It works due the overload resolution, but OP, seems to me does not catch on that. So responding on this: read Method Group, is not an answer. – Tigran Jun 18 '14 at 15:39
  • I can understand Marc Gravell's answer in the linked question as applying to my question, but I would never have found it by searching - I had no idea what a method group was. It's certainly enlightening though! – Geoff Jun 18 '14 at 15:40
  • 1
    @Geoff: correct and good for you. but for sake of correctness of *this* post, it should be answered correctly, or at least marked dupplicate with *correct* question already asnwered by someone. – Tigran Jun 18 '14 at 15:41
  • @Tigran selman22 is right, this is related to method groups. This is not related to overload resolution at all. – dcastro Jun 18 '14 at 16:16

4 Answers4

4

Any needs a function (Func) that (and I'm assuming that stringArray is just a string)

  1. takes a char input
  2. returns a bool.

The most common way to use this is by making an inline anonymous function (a lambda expression). However, you can pass an actual function instead. The system will look through the arguments and return type to make sure it matches up, just like a lambda statement.

It just so happens that the function Contains takes a char as an input and returns a bool. That's why you can pass the name of the function instead of of calling it (using parentheses with an argument list).

Take for example if we made our own function:

public static bool Contains2 (this string input, char c)
{
    //....
}

stringArray.Any(stringToCheck.Contains2)

This would also fit the bill. Notice how there are no () parentheses on Contains2. This is because we are passing the function itself.

Your lambda also works because it takes a char input (s =>) and returns a bool (the result of Contains(s)).

gunr2171
  • 16,104
  • 25
  • 61
  • 88
  • Thanks - the real 'aha' moment for me was your note about passing the function itself. – Geoff Jun 18 '14 at 16:01
  • @Geoff, just so you know, it's the same with lambdas. You are still just passing a full function, the only difference is you are making the function body inline, rather than pointing to an existing function. – gunr2171 Jun 18 '14 at 16:03
1

Because Any method requires Delegate Func<TSource, bool>, and if Contains method satisfy it, we can send method itself, instead of creating new anonymous method, that will be just wrapper around stringToCheck.Contains(s)

Sergey Litvinov
  • 7,408
  • 5
  • 46
  • 67
0

nIt's a method group. There's only one parameter so the compiler can determine what can be passed in. In other words the stringToCheck.Contains method has the same signature then the Any.

Bartosz Wójtowicz
  • 1,321
  • 10
  • 18
-1

Because here is used Any overload:

public static bool Any<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate
)

where

predicate is your stringToCheck.Contains method.

Tigran
  • 61,654
  • 8
  • 86
  • 123
  • SO is an english forum... please post english links. – tnw Jun 18 '14 at 15:32
  • @Tigran The title is misleading - but what the OP wants to know is the difference between a lambda expression (`s => stringToCheck.Contains(s)`) and a method group (`stringToCheck.Contains`). That being the case, this does not answer the question. – dcastro Jun 18 '14 at 15:42
  • @dcastro: "My question is, how is it that the Contains() term doesn't require an explicit parameter? " Looks to me like clear question. So the answer is: as there is an overload of Any, that lets your code compile and work even without paremeter specified, as predicates may work in that way. – Tigran Jun 18 '14 at 15:44
  • @Tigran exactly, he's asking why Contains doesn't require an explicit parameter. He's not asking about the Any method. You seem to be confused. – dcastro Jun 18 '14 at 16:11