Синтаксис {} является инициализатором коллекции. Код эквивалентен
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 - это функция, которая вызывает другую функцию и передает строку. Это так:
foreach(string s in b) {
if(FunctionToCall(s) == true) b.Remove(s);
}
a.Contains - это функция, которая принимает строку и возвращает bool. Таким образом, код можно изменить на:
foreach(string s in b) {
if(a.Contains(s)) b.Remove(s);
}
Обратите внимание, что в этом лямбда-синтаксисе вы передаете функцию "a.Contains" - а не результат функции! Это как указатель на функцию. RemoveAll ожидает, что примет функцию в виде "bool FunctionName (string input)".
Редактировать: Вы знаете, что такое делегаты? Они немного похожи на указатели на функции: делегат задает сигнатуру («принимает 2 строки, возвращает int»), а затем вы можете использовать ее как переменную. Если вы не знаете о делегатах, прочитайте статью Карла Сегинса .
Некоторые делегаты нужны крайне часто, поэтому разработчики .net Framework добавили три типа чрезвычайно распространенных делегатов:
- Predicate: делегат, который принимает T и возвращает bool.
- Действие: делегат, который принимает от 1 до 4 параметров и возвращает void
- Функция: делегат, который принимает от 0 до 4 параметров и возвращает T
(Бесстыдно скопировано с Джона Скита Ответ здесь )
Итак, предикат - это просто имя, данное делегату, так что вам не нужно указывать его самостоятельно.
Если в вашей сборке есть ЛЮБАЯ функция с подписью
"bool YourFunction (строка чего-либо)", это Predicate<string>
и может быть передано в любую другую функцию, которая принимает одну:
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);
}
Весь смысл в разделении интересов (см. Комментарий в SomeGenericFunction), а также в том, чтобы иметь очень общие функции. Посмотрите на мою универсальную, расширяемую функцию кодирования строк . При этом используется Func, а не делегат Predicate, но цель та же.