c#: Enumerable Class 中的 Where()、OrderBy() 和 Select() 不应该采用委托类型、lambda 表达式或匿名类型作为参数
c#: Isn't Where(), OrderBy() and Select() from Enumerable Class supposed to take a delegate type, lambda expression or anonymous type as a parameter
我有一个问题。查看两个代码块。来自 IEnumerable
Class 的 Where()
、OrderBy()
和 Select()
不应该采用委托类型、lambda 表达式或匿名类型作为参数。如果是这样,QueryOverStringWithRawDelegate()
是如何产生与 QueryOverStringsWithExtensionMethods()
相同的结果的?
void QueryOverStringsWithExtensionMethods()
{
// Assume we have an array of strings
string[] currentVideoGames = { "Morrowind", "Uncharted 2", "Fallout 3", "Daxter", "Bio Shock 4" };
IEnumerable<string> subset = currentVideoGames.Where(game => game.Contains(" ")).OrderBy(game => game).Select(delegate (string game) { return game; });
Console.WriteLine("Query Over Strings With Extension Method");
foreach (var s in subset)
{
Console.WriteLine("Items: {0}", s);
}
}
和
void QueryStringsWithRawDelegates()
{
// Assume we have an array of strings
string[] currentVideoGames = { "Morrowind", "Uncharted 2", "Fallout 3", "Daxter", "Bio Shock 4" };
var subset = currentVideoGames.Where(Filter).OrderBy(ProcessItems).Select(ProcessItems);
foreach (var s in subset)
{
Console.WriteLine("Items: {0}", s);
}
string ProcessItems(string game)
{
return game;
}
bool Filter(string game)
{
return game.Contains(" ");
}
}
感谢您的帮助!
不,正如您所观察到的,这不是错误。编译器会将具有适当签名的方法组翻译成相应的 Func<> 类型。
currentVideoGames.Where(Filter)
只是 shorthand 用于:
currentVideoGames.Where(new Func<string, bool>(Filter))
也就是说,编译器看到你有一个采用委托类型 Func<string, bool>
的方法,它看到你给它一个具有签名 bool Filter(string)
的方法(严格,一个或多个重载的方法组,其中一个具有足够接近的签名),它会自动插入代码以实例化一个新的委托实例。
这种相同的语言功能让您可以编写如下内容:
SomeEvent += Handler;
而不是:
SomeEvent += new EventHandler(Handler);
同样:
currentVideoGames.Where(game => game.Contains(" "))
是 shorthand 为:
currentVideoGames.Where(new Func<string, bool>(CompilerGeneratedFunction))
其中 CompilerGeneratedFunction
看起来像:
bool CompilerGeneratedFunction(string x)
{
return x.Contains(" ");
}
See this on SharpLab。碰巧编译器将 CompilerGeneratedFunction
(它称为 <M>b__0_0
)放在一个新的内部 class 中,并缓存它出于性能原因实例化的 Func<string, bool>
。
我有一个问题。查看两个代码块。来自 IEnumerable
Class 的 Where()
、OrderBy()
和 Select()
不应该采用委托类型、lambda 表达式或匿名类型作为参数。如果是这样,QueryOverStringWithRawDelegate()
是如何产生与 QueryOverStringsWithExtensionMethods()
相同的结果的?
void QueryOverStringsWithExtensionMethods()
{
// Assume we have an array of strings
string[] currentVideoGames = { "Morrowind", "Uncharted 2", "Fallout 3", "Daxter", "Bio Shock 4" };
IEnumerable<string> subset = currentVideoGames.Where(game => game.Contains(" ")).OrderBy(game => game).Select(delegate (string game) { return game; });
Console.WriteLine("Query Over Strings With Extension Method");
foreach (var s in subset)
{
Console.WriteLine("Items: {0}", s);
}
}
和
void QueryStringsWithRawDelegates()
{
// Assume we have an array of strings
string[] currentVideoGames = { "Morrowind", "Uncharted 2", "Fallout 3", "Daxter", "Bio Shock 4" };
var subset = currentVideoGames.Where(Filter).OrderBy(ProcessItems).Select(ProcessItems);
foreach (var s in subset)
{
Console.WriteLine("Items: {0}", s);
}
string ProcessItems(string game)
{
return game;
}
bool Filter(string game)
{
return game.Contains(" ");
}
}
感谢您的帮助!
不,正如您所观察到的,这不是错误。编译器会将具有适当签名的方法组翻译成相应的 Func<> 类型。
currentVideoGames.Where(Filter)
只是 shorthand 用于:
currentVideoGames.Where(new Func<string, bool>(Filter))
也就是说,编译器看到你有一个采用委托类型 Func<string, bool>
的方法,它看到你给它一个具有签名 bool Filter(string)
的方法(严格,一个或多个重载的方法组,其中一个具有足够接近的签名),它会自动插入代码以实例化一个新的委托实例。
这种相同的语言功能让您可以编写如下内容:
SomeEvent += Handler;
而不是:
SomeEvent += new EventHandler(Handler);
同样:
currentVideoGames.Where(game => game.Contains(" "))
是 shorthand 为:
currentVideoGames.Where(new Func<string, bool>(CompilerGeneratedFunction))
其中 CompilerGeneratedFunction
看起来像:
bool CompilerGeneratedFunction(string x)
{
return x.Contains(" ");
}
See this on SharpLab。碰巧编译器将 CompilerGeneratedFunction
(它称为 <M>b__0_0
)放在一个新的内部 class 中,并缓存它出于性能原因实例化的 Func<string, bool>
。