理解linq语法

时间:2012-06-01 07:54:26

标签: c# .net linq syntax

我很难理解它的内部工作 这是LINQ语法

string[] test = new test[] { "abc", "", "cd", "", "aa" };
test = test.Where(x => !string.IsNullOrEmpty(x)).ToArray();

我对它的语法管理方式感到困惑。它把所有数组放在x?如果是,那么它如何管理x null值?

如果没有那么测试数组值一个接一个地放在x?

3 个答案:

答案 0 :(得分:10)

您应该考虑其余的答案,它们非常准确,我想向您展示,也许这将有助于您理解语法是这种查询实际上可以用这样的查询语法表示:

string[] test=new test[]{"abc","","cd","","aa"};

// this is the equivalent to your code
// added explicit type to make it clearer, it's optional
var a = from (string)x in test
        where !string.IsNullOrEmpty(x)
        select x;

如果你熟悉SQL,你会发现这种语法更容易阅读,即使你不知道它,这种语法也更清晰。

编译代码时,此查询语法会自动转换为C#方法语法,以生成IL,因此,如果您解密DLL,您将看到方法语法而不是查询语法

关于此代码的简要说明:

  • 正如您所看到的,x变量已声明且类型为string。为什么?因为你的数组是一个字符串数组

  • in test表示要迭代的来源IEnumerable<> - 在这种情况下您的数组

  • where非常明确,它只是从数组中选择所有非空字符串

  • 最后选择实际上是数据的投影。

所有这些都等同于你的代码

现在你可能会问自己......什么时候应该使用一种语法?它们是等价的,但查询语法运算符是有限的,这意味着大多数操作都是使用方法语法而不是查询语法完成的。我一直在做的是尝试编写代码更容易阅读一些代码更容易理解,如果它是用查询语法编写的。

关于方法语法,x => ...语法被称为lambda表达式,如果它是第一次使用它们,它们可能看起来很奇怪,但你最终会喜欢它们。

基本上lambda是代表的快捷方式,所以你在做什么:

x => !string.IsNullOrEmpty(x)

您正在创建匿名方法,并且该方法正在分配给delegate参数。 x代表string variable

这个主题非常广泛,试图在这里解释一下,但我希望这能让你了解背后的内容。

顺便说一句,您可以将语法结合起来:

// this is the equivalent to your code
// added explicit type to make it clearer, it's optional
var a = (from (string)x in test
        where !string.IsNullOrEmpty(x)
        select x).ToArray();

如果你谷歌LINQ就像谷歌搜索pol lol一样,网络上充斥着LINQ文章,样本等。

一个很好的起点是微软的101个样本

http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

修改

我将尝试模拟Where方法,以便您可以获得更好的lambda表达式示例

// this is basically the declaration of one overload of the Where method
// the this in the parameter declaration, indicates this is an extension method which will be available to all IEnumerable<> objects
// the Func<T, bool> is the interesting part, it is basically a delegate (as a reminder, the last parameter of the Func object indicates the type that must be returned, in this case is a bool)
// the delegate is simply a pointer to a function 
public IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{

   ...some logic




   ... yielding back the reuslts
   foreach(var r in res)
   {
      // here is the delegate in action
       if(predicate(r))
           yield return r;
   }
}

正如您所看到的,委托被称为函数(委托是指向函数的指针) 对接什么功能???您在代码中声明的那个

  • x => !string.IsNullOrEmpty(x)x表示从Where方法传回外部代码的参数,您可以在其中检查并使用它来过滤结果

  • x =&gt; 是声明委托的缩写

  • !string.IsNullOrEmpty(x)这是您匿名方法的正文,您可以看到它符合{{1}的要求它返回一个bool(用于过滤数组元素的谓词),作为参数,它接收到通用Func<T, bool>,在本例中是一个来自数组的字符串

声明lambda表达式的另一种方法是:

T

使用这种语法很容易证明它们实际上是方法(匿名方法)

答案 1 :(得分:6)

我们可以将该陈述拆开并一次检查一件

x => !string.IsNullOrEmpty(x)基本上定义了类似下面的函数

bool Filter(string x){
   return !string.IsNullOrEmpty(x)
}

并基于该函数创建谓词。谓词只是一个委托 - 一个可以传入变量的函数。

.Where是一种扩展方法,为了简单起见,可以定义

IEnumerable<T> Where<T>(this IEnumerable<T> sequence,Predicate<T> pred){
   foreach(var elem in sequence){
       if(pred(elem)){
          yield return elem;
       }
   }
}

你有没有定义函数,因为Filter定义在上面,而不是使用lambda你的语句看起来像这样

test = test.Where(Filter).ToArray(); 

因此,通过在数组上调用此扩展方法并传递上述谓词,您将迭代数组中的所有元素并返回与谓词匹配的所有元素(即那些既不为null也不具有空值的元素字符串)

最后,您调用扩展方法.ToArray(),将.Where返回的内容(IEnumerable<string>)转换为数组

答案 2 :(得分:2)

修改

阅读这篇文章,你肯定会知道你有写作......

C# 3.0 New Language Features (Part 1)

C# 3.0 New Language Features (Part 2)


来自C {3.0的extenstion method + lambda experssion部分

此处为此代码

test=test.Where(x => !string.IsNullOrEmpty(x)).ToArray();

where - 是一种extesion方法

x => !string.IsNullOrEmpty(x) - 是lambda expresion,它取代了匿名函数

这整个函数检查数组的每个元素...即lamdaba表达式检查数组的每个元素是否满足写入的条件并最终返回满足条件的那些元素的数组