Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

string.Contains as a predicate not a function call?

Tags:

c#

linq

predicate

I found this sample of code on SO (can't remember from where :/) that allowed me to check for line code arguments when launching my application :

if (e.Args.Length == 0 || e.Args.Any("-show".Contains))
{
  //show interface...
}

I just can't seem to understand how the "-show".Contains works. And if there's any difference with a (classic) x => x.Contains('"-show") (except for the evident typing gain).

Works like a charm but I'd like to understand why, I feel like something big is hapening.

like image 520
Phoque Avatar asked May 03 '18 09:05

Phoque


4 Answers

This:

.Any("-show".Contains)

is basically shorthand for this:

.Any(s => "-show".Contains(s))

The Any method takes a delegate as a parameter and you can create that delegate in a number of ways. The first snippet uses a method group while the second uses a Lambda.

It's not really accurate to say that the first is shorthand for the second because method groups predate Lambdas, but if you think in terms of Lambdas when calling LINQ methods like Any then it is effectively the case.

like image 189
jmcilhinney Avatar answered Nov 14 '22 14:11

jmcilhinney


As @jmcilhiney already said, it shorthand for:

.Any(s => "-show".Contains(s))

Contains is a function accepting 1 parameter which is of type string (and returns a boolean). Any() in this case wants a function that needs 1 param which is a string and that returns a boolean. So rather than adding an extra lambda warapper s=>, you can directly return .Contains

In technical terms this is a:

Func<string, boolean> //1 param string, output: boolean

Note that this code matches any argument that is a part of -show

thus either of the following arguments do match!

-show
-s
sh
ow
h
w
// etc..
like image 4
Joel Harkes Avatar answered Nov 14 '22 13:11

Joel Harkes


Any() expects a Func<TSource, bool> delegate. So any function that returns a bool and takes an argument that is of the same type as the elements of the collection (string in your case) can be applied. This can be an existing function, or a lambda expression.

The signature of String.Contains is

bool Contains(string s)

That's why you can pass it to Any()

like image 4
adjan Avatar answered Nov 14 '22 13:11

adjan


The equivalent would be x => "-show".Contains(x) rather than what you've shown.

After that you'll realise that all you're doing by introducing the x based lambda is to create a function accepting a single string argument and returning a bool and wrapping a function that accepts a single string and returns a bool. There's no need for the wrapper.

like image 1
Damien_The_Unbeliever Avatar answered Nov 14 '22 15:11

Damien_The_Unbeliever