The { } Syntax is a collection initializer. The code is equivalent to
List<string> a = new List<string>();
a.Add("a");
a.Add("b");
a.Add("c");
List<string> b = new List<string>();
b.Add("a");
b.Add("b");
b.Add("c");
b.Add("d");
b.Add("e");
b.Add("f");
b.RemoveAll is a function that calls another function and passes in a string. It's like this:
foreach(string s in b) {
if(FunctionToCall(s) == true) b.Remove(s);
}
a.Contains is a function that takes a string and returns a bool. So the code can be changed to:
foreach(string s in b) {
if(a.Contains(s)) b.Remove(s);
}
Note that in this Lambda-Syntax, you are passing the "a.Contains" function - not the result of the function! It's like a function pointer. RemoveAll expects to take a function in the form of "bool FunctionName(string input)".
Edit: Do you know what delegates are? They are a bit like function pointers: A delegate specifies a signature ("Takes 2 strings, returns an int"), and then you can use it like a variable. If you don't know about delegates, read Karl Seguins article.
Some delegates are needed extremely often, so the .net Framework developers added three types of extremely common delegates:
- Predicate: A delegate that takes a T and returns a bool.
- Action: A delegate that takes 1 to 4 parameters and returns void
- Function: A delegate that takes 0 to 4 parameters and returns a T
(Shamelessly copied from Jon Skeet's Answer here)
So predicate is just the name given for a delegate, so that you don't have to specify it yourself.
If you have ANY function in your assembly with the signature
"bool YourFunction(string something)", it is a Predicate<string>
and can be passed into any other function that takes one:
public bool SomeFunctionUsedAsPredicate(string someInput)
{
// Perform some very specific functionality, i.e. calling a web
// service to look up stuff in a database and decide if someInput is good
return true;
}
// This Function is very generic - it does not know how to check if someInput
// is good, but it knows what to do once it has found out if someInput is good or not
public string SomeVeryGenericFunction(string someInput, Predicate<string> someDelegate)
{
if (someDelegate.Invoke(someInput) == true)
{
return "Yup, that's true!";
}
else
{
return "Nope, that was false!";
}
}
public void YourCallingFunction()
{
string result = SomeVeryGenericFunction("bla", SomeFunctionUsedAsPredicate);
}
The whole point is separation of concerns (see the comment in SomeGenericFunction) and also to have very generic functions. Look at my generic, extensible string encoding function. This uses the Func rather than the Predicate delegate, but the purpose is the same.