2012-03-09 72 views
0

我的一位同事和我今天正在讨论Linq。特别是在使用查询理解之前需要包含System.Linq命名空间(通过使用)。我当时认为这样做是为了不太可能错误地使用非Linq扩展方法,但我们从来没有得出任何结论。为什么在使用查询解析时应该/不应该包含System.Linq名称空间?LINQ查询解析 - 为什么需要System.Linq命名空间?

+2

对不起,但这不是一个真正的问题。这种推理的逻辑结论是,我们不应该写任何“使用”陈述;编译器应该把它全部弄清楚。 – Yuck 2012-03-09 00:30:25

+0

@Yuck - 也许这将是一个更美好的世界,如果它确实存在(我知道这样会有很多问题需要解决)。 – 2012-03-09 00:32:27

+2

@ M.Babcock:不,因为那时我们遇到了命名空间碰撞,智能污染等问题。最接近你的是有ReSharper/CodeRush /等工具。如果没有任何歧义,自动为您使用使用语句。 – 2012-03-09 00:34:20

回答

3

这听起来很明显,但是当我们打算使用框架提供的LINQ工具时,应该包含System.Linq名称空间。但是没有任何东西阻止我们使用我们自己的,编译器也不介意。

例如,下面的(愚蠢的,但完整的!)的代码片段编译和运行得很好:

// no usings at all 
static class DumbLinq 
{ 
    static int Select(this int i, System.Func<int, int> f) 
    { 
     // actually, our Select is a negation operator in disguise 
     return -i; 
    } 

    static void Main() 
    { 
     int i = 10; 
     var j = from n in i 
       select n; 
     System.Console.WriteLine(j); // prints -10 
    } 
} 

编译器只是变换查询理解语法为“流体”语法它编译的代码之前。一旦找到合适的方法使用,它照常进行。通过usingSystem.Linq我们确保编译器能够找到支持使用LINQ的查询的类和接口,仅此而已。

+0

+1 - 你的示例比我的短一半线:)。 – 2012-03-09 01:49:48

+0

谢谢 - 我试图写这样的东西,但我认为我的方法签名并不完全正确。 – 2012-03-09 23:57:54

0

因为Linq库就是这样一个库。如果你不需要它,那么不要将它包含在内存空间中,或者引用DLL。

但linq功能基本上是针对IEnumerable<T>运行的,它们只是方法,当您要使用查询语法时,只需要C#编译器中的少量糖。

+0

这不是一个包含参考的问题。 System.Linq的内容位于程序集System.Core中。这是通过'using'包含命名空间的问题。 – recursive 2012-03-09 00:39:44

+0

是的。 System.Linq命名空间包含对付的方法调用,有时会返回IEnumerable 。他们添加使用语句的原因是为了处理突变的问题。如果你在遗留代码中实现了“选择”方法,现在Linq被奇迹般地添加到你的默认命名空间中,那么旧代码在升级后突然中断:( – Spence 2012-03-09 00:43:16

3

不,您不需要包含System.Linq以便查询解析工作 - 请参阅示例。

using System; 
using System.Collections.Generic; 

namespace SelectQuery 
{ 

    internal static class MyExtensions 
    { 
     public static IEnumerable<int> Select(this int[] items, Func<int, int> selector) 
     { 
      return items; 

     } 
    } 

    class Program 
    { 

     static void Main(string[] args) 
     { 
      int[] data = new[] { 1, 2, 34 }; 

      var result = from v in data select v; 
      foreach (var i in result) 
      { 
       Console.WriteLine(i); 
      } 
     } 
    } 
}