我很难理解为什么我会得到我的结果。
我有两个字符串列表:
var list1 = new List<String> {"item 1", "item 2"};
var list2 = new List<String> { "item 3", "item 4" };
版本1 - 输出:“第2项”
var item =
from x in (list1.Concat(list2))
where x.EndsWith("2")
select x;
Console.WriteLine(item.First());
第2版 - 输出:“i”
var item =
from x in (list1.Concat(list2))
where x.EndsWith("2")
select x.First();
Console.WriteLine(item.First());
版本3 - 输出:“System.Linq.Enumerable + WhereEnumerableIterator`1 [System.String]”
var item =
from x in (list1.Concat(list2))
where x.EndsWith("2")
select x;
Console.WriteLine(item);
鉴于版本2输出“i”,我希望版本3输出“第2项”。为什么会出现这种情况?
答案 0 :(得分:5)
在版本3中,select x
返回与您的critera匹配的序列字符串;它恰好是一个包含一个项目的序列。
Console.WriteLine
都会内部调用.ToString()
。由于IEnumerable<T>
没有有意义的字符串表示形式,因此.NET中的默认值是打印该类型的字符串名称。
根据你的措辞,我认为你的混淆部分来自于误解为什么版本2的工作方式。在版本2中,select x.First()
实际上有点奇怪/巧合,因为字符串也 IEnumerable<char>
,因此您可以对字符串执行LINQ操作。对于符合条件的每个结果,.First()
会返回该char
序列的第一个元素。所以你要说:
&#34;对于符合我标准的每个元素,选择第一个字符,然后返回匹配的所有第一个字符的序列。&#34;
事实上,版本2中的item
是IEnumerable<char>
,其中包含一个元素。在Console.WriteLine()
上拨打IEnumerable<char>
只会按顺序打印字符。所以你得到了&#34;我&#34;。
(注意:我在回答此问题后看到,问题已被编辑,以便在投影内部和结果中调用.First()
,因此有关将IEnumerable<char>
传递给Console.WriteLine
的问题并非如此。 #39; t完全相关了)
请记住,LINQ几乎是关于使用集合,直到您明确地减少它们为止。例如,Select
只是一个投影或转换。它返回传递给它的相同数量的项目,进行转换。 Where
减少了集合,但它仍然是一套。
答案 1 :(得分:2)
您的版本2正在从字符串x.First()
中选择第一项/字符,而您的第一个版本是从结果集中选择第一项 - &gt;第一串。
版本1类似于 - 从结果集中选择第一个项目
var item = (from x in (list1.Concat(list2))
where x.EndsWith("2")
select x).First(); //First complete string will be selected
和版本2类似 - 从结果集中的字符串中选择第一项
var item = from x in (list1.Concat(list2))
where x.EndsWith("2")
select x.First(); //only first char will be selected for string
您的第三种情况是选择IEnumerable<string>
,因此当您致电Console.WriteLine
时,它会调用ToString
的默认实施,从而获得
“System.Linq.Enumerable + WhereEnumerableIterator`1 [System.String]”
答案 2 :(得分:0)
使用First()
时,您正在实现列表,导致迭代器执行。这是急切的执行。你的第三个版本使用的select
没有实现列表abd使用返回迭代器的Defeered Execution
,因此在它上面调用ToString()
返回迭代器名称
答案 3 :(得分:0)
因为Where
会返回IEnumerable
。
你写的相当于:
var whoKnows = list1.Concat(list2).Where(x => x.EndsWith("2"));
Console.WriteLine(whoKnows);
集合的ToString
只返回类名。
答案 4 :(得分:0)
版本2中x
的类型为String
。版本1中item
的类型是IEnumerable。
因此,您的版本2返回一个字符列表,这些字符是每个字符串的第一个字符。在版本1中,item.First()
返回结果集的第一个元素,即字符串。
答案 5 :(得分:0)
//This raise a exception if no item found
var item=list1.Concat(list2).First(i => i.EndsWith("2"));
//this return default value (null) if no item found
var item2 = list1.Concat(list2).FirstOrDefault(i => i.EndsWith("2"));