10

我真的很困惑理解它的内部工作这是 LINQ 语法

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

我对它如何管理语法感到困惑。是否将所有数组都放在x中?如果是,那么它如何管理 x 空值?

或者

如果不是,则将测试数组值一一放入 x 中?

4

3 回答 3

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 表达式,如果您是第一次使用它们,它们可能看起来很奇怪,但最终您会喜欢它们。

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

x => !string.IsNullOrEmpty(x)

您正在创建一个匿名方法,并且该方法被分配给委托参数。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 就像谷歌搜索 porm 大声笑,网络上充斥着 LINQ 文章、示例等。

一个好的开始点是来自 Microsoft 的 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 =>是声明委托的缩写

  • !string.IsNullOrEmpty(x)这是您的匿名方法的主体,正如您所看到的,它满足Func<T, bool>返回布尔值(过滤数组元素的谓词)的要求,并且作为参数,它接收到泛型T,在这种情况下是数组中的字符串

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

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

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

于 2012-06-01T08:07:38.140 回答
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返回的 (an IEnumerable<string>) 转换为数组

于 2012-06-01T08:41:11.913 回答
2

编辑

阅读这篇文章,您一定会对您所写的内容有所了解......

C# 3.0 新语言特性(第 1 部分)

C# 3.0 新语言特性(第 2 部分)


它来自 C# 3.0 的扩展方法+ lambda experssion部分

在这段代码中

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

where- 是一种扩展方法

x => !string.IsNullOrEmpty(x)- 是 lambda 表达式,它是匿名函数的替换

这整个函数检查数组的每个元素......即 lamdaba 表达式检查数组的每个元素是否满足写入的条件,然后最终重新调整满足条件的那些元素的数组

于 2012-06-01T07:55:56.087 回答