是否可以在C#/ LINQ中扩展查询关键字?

时间:2011-08-31 09:06:57

标签: c# linq select

是否可以使用自己的定义扩展Linq的查询关键字(如:select,where等)?

Codeexample以使其更清晰:

System.Collections.Generic.List<string> aList = 
    new System.Collections.Generic.List<string> { "aa", "ab", "ba", "bb" };

// instead of
string firstString = (from item in aList
                      where item.StartsWith("a")
                      select item).First();

// would be nice
string firstString = from item in aList
                     where item.StartsWith("a")
                     selectFirst item;

// or something else
from item in aList
where item.StartsWith("a")
WriteLineToConsole item;

我认为这是不可能的,但仍然希望;)

3 个答案:

答案 0 :(得分:7)

您无法添加自己的内容关键字,但可以影响现有关键字的含义。

例如,此代码:

string firstString = (from item in aList
                      where item.StartsWith("a")
                      select item).First();

有效地预处理为:

string firstString = aList.Where(item => item.StartsWith("a"))
                          .First();

...因此,如果您更改WhereFirst方法调用的含义,则可以影响该行为。

如果你有胃口,你可能想看看我前一段时间写的this Stack Overflow answer,它在某些情况下改变了LINQ to Entities中where的行为。这是邪恶的,邪恶的代码。

答案 1 :(得分:6)

实现这一目标的一种方法是编写一个预处理器,它将自定义LINQ关键字转换为标准LINQ关键字,然后再将其提供给编译器。顺便说一句它是如何使用标准LINQ关键字的。预处理器将它们转换为常规扩展方法(.Select,。Where,。GroupBy,...),然后将其提供给不了解这些关键字的编译器。

当然,这样做会失去Intellisense,但这可以通过编写Visual Studio扩展来解决。对于这种糖,可能会做很多工作。

答案 2 :(得分:4)

不,在语言规范或任何当前的C#编译器中都不可能。你在那里创造的任何东西都不再是(纯粹的)C#。