List<string> a = new List<string>() { "a", "b", "c" };
List<string> b = new List<string>() { "a", "b", "c", "d", "e", "f" };
b.RemoveAll(a.Contains);
如果你循环浏览b,它现在只包含d e和f。任何人都可以扩展实际发生的事情,因为目前它根本没有任何意义。
编辑:我更多地谈论谓词的使用。怎么知道如何将内容传递到哪里?
答案 0 :(得分:6)
b.RemoveAll(<function that takes a string and returns true if we want to remove it>)
不需要lambda表达式。
也许你想要读一行
b.RemoveAll(x => a.Contains(x))
但是,函数 x=> a.Contains(x)
只是一个函数,它接受一个字符串并返回一个bool,指示是否包含x。 a.Contains已经是一个能够做到这一点的功能。
答案 1 :(得分:5)
{}语法是一个集合初始值设定项。代码等同于
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);
}
请注意,在此Lambda-Syntax中,您传递的是“a.Contains”函数 - 而不是函数的结果!它就像一个函数指针。 RemoveAll 期望以“bool FunctionName(字符串输入)”的形式获取一个函数。
编辑:您知道代表是什么吗?它们有点像函数指针:委托指定签名(“取2个字符串,返回一个int”),然后你可以像变量一样使用它。如果您不了解代表,请阅读Karl Seguins article。
非常需要一些代表,因此.net Framework开发人员添加了三种非常常见的委托:
(从Jon Skeet的Answer here无耻地复制)
因此谓词只是委托给出的名称,因此您不必自己指定。
如果装配中有任何带有签名的功能
“bool YourFunction(string something)”,它是一个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中的注释)以及非常通用的函数。看看我的generic, extensible string encoding function。这使用Func而不是Predicate委托,但目的是相同的。
答案 2 :(得分:3)
这样看:
foreach(string s in b)
{
if(a.Contains(s))
b.Remove(s);
}
将if evaluate子句中的位作为委托传递(托管等效于函数指针)。 RemoveAll
方法展开列表并完成剩下的工作。
答案 3 :(得分:2)
它表示'删除b中包含的所有元素'。所以你只留下b中那个不存在于a中的那个。
答案 4 :(得分:1)
以下是代码的略微扩展版本,其中显示了正在发生的事情:
List<string> a = new List<string> () { "a", "b", "c" };
List<string> b = new List<string> () { "a", "b", "c", "d", "e", "f" };
Predicate<string> ps = a.Contains;
b.RemoveAll (ps);
答案 5 :(得分:0)
对于b
中的每个元素,正在为该元素评估a.Contains()
。如果确实如此,则将其删除。
因此,您要删除b
中包含的a
中的每个元素。
函数“a.Contains
”作为参数传递给RemoveAll
。
答案 6 :(得分:0)
RemoveAll的签名看起来像这样......
public int RemoveAll(Predicate<T> match);
Predicate<T>
是一个代表,它接受Ts并返回bools ...
public delegate bool Predicate<T>(T obj)
因此,RemoveAll要求引用一个方法,在您的情况下,该方法将接受字符串并返回bool。 List<T>.Contains
就是这样一种方法。您会注意到List<T>.Contains
的签名与Predicate委托匹配(它需要Ts并返回bools)...
public bool Contains(T item);
RemoveAll会将谓词作为“匹配”传递给调用它的列表中的每个元素(在您的情况下为b)。因此,如果a.Contains("a")
例如返回true,那么将从b列表中删除所有a。因此,在您的示例中,所有a,b和c都被删除。
使用像.NET Reflector这样的工具可以让你查看RemoveAll的代码,这可能有助于澄清幕后发生的事情。