我真的很困惑理解它的内部工作这是 LINQ 语法
string[] test = new test[] { "abc", "", "cd", "", "aa" };
test = test.Where(x => !string.IsNullOrEmpty(x)).ToArray();
我对它如何管理语法感到困惑。是否将所有数组都放在x中?如果是,那么它如何管理 x 空值?
或者
如果不是,则将测试数组值一一放入 x 中?
您应该考虑其余的答案,它们非常准确,我想向您展示的内容可能会帮助您理解语法,因为这种查询实际上可以用如下查询语法表示:
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();
使用这种语法很容易表明它们实际上是方法(匿名方法)
我们可以把声明拆开,一次一个地检查
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>
) 转换为数组
编辑
阅读这篇文章,您一定会对您所写的内容有所了解......
它来自 C# 3.0 的扩展方法+ lambda experssion部分
在这段代码中
test=test.Where(x => !string.IsNullOrEmpty(x)).ToArray();
where
- 是一种扩展方法
x => !string.IsNullOrEmpty(x)
- 是 lambda 表达式,它是匿名函数的替换
这整个函数检查数组的每个元素......即 lamdaba 表达式检查数组的每个元素是否满足写入的条件,然后最终重新调整满足条件的那些元素的数组