我们说我有一个名为names
的列表:
List<string> names = new List<string> { "Mike", "Steve", "Alan", "John" };
现在,如果我在列表List<T>.Sort
上使用names
方法:
names.Sort();
列表names
将被排序:
&#34; Alan&#34;,&#34; John&#34;,&#34; Mike&#34;,&#34; Steve&#34;
我们假设我在初始列表OrderBy
上使用LINQ Sort
而不是names
:
names.OrderBy(x => x);
初始列表names
不会被排序:
&#34; Mike&#34;,&#34; Steve&#34;,&#34; Alan&#34;,&#34; John&#34;
我知道是否要使用LINQ names
对列表OrderBy
进行排序我必须将查询分配给变量:
var orderedNames = names.OrderBy(x => x);
初始列表names
保持未分类,但orderedNames
将保留初始列表的已排序名称:
&#34; Alan&#34;,&#34; John&#34;,&#34; Mike&#34;,&#34; Steve&#34;
我很好奇为什么没有编译器警告没有分配给变量的LINQ查询,因为调用names.OrderBy(x => x);
而不首先将它分配给变量是没用的。
答案 0 :(得分:10)
为什么没有编译器警告没有分配给变量的LINQ查询
这是一个功能。默认情况下不存在功能,必须将其删除。需要考虑,设计,指定,实施,测试,记录和发送功能。
所有这些都需要发生才能让你拥有这个功能。他们都没有发生。因此,没有任何特征。
如果您想要实施此功能,请选择它。编译器是开源的。如果你想提倡其他人实施它,那就去吧;设计过程也是公开的。
如果你要实施它,那么当你在它上面时,你也可以在字符串上查找调用Trim
或ToLower
等内容的内容。从未使用过。
现在,请注意&#34;未分配给变量&#34;不够。例如:
names.OrderBy(whatever).ToList().ForEach(whatever);
不对变量赋予任何内容,但您不想对此发出警告。类似地
Foo(names.OrderBy(whatever))
通过调用分配给变量(参数),而不是赋值。
类似地
x = y ? names.OrderBy(whatever) : whatever;
不直接分配,但仍使用该值。 要非常小心。编译器已经有一个检测器可以正确地确定表达式是否用于其值,因此请研究。
现在,也许你的问题是&#34;什么是困难或其他反对&#39;做这样的功能?&#34;
问题始终是误报。误报是代码正常工作的场景,它可以像开发人员想要的那样工作,代码可以被读者理解,并且仍然会收到警告。最好的误报让开发人员烦恼,但情况变得更糟。误报可能会破坏对编译器的信任,并且可能导致人们将工作代码更改为不会发出警告的错误代码。
让我们来看一个微妙的案例。假设我们有这样可怕的东西:
giraffes.Select(g => { g.Feed(); return 1; }).ToList();
这是可怕的代码。但警告不得类似于&#34;包含查询的表达式语句无用&#34;,因为这是误报。用户正在做一些非常非常错误的事情,但他们不进行无用的查询;这个查询提供了所有的长颈鹿。
这里的错误是编写一个仅对其副作用有用的查询。查询不应该有副作用,这是编写foreach(var g in giraffes) g.Feed();
警告必须不仅仅是准确 99.99%的时间,他们必须尽可能识别真正的问题。这是一个超级难题,编译团队已经有了足够的问题。
这里有一个教训,那就是:考虑一下在设计语言时你想要阻止的不良做法。 C#非常擅长防止C和C ++程序员陷入的许多经典坏习惯。 (还有一些Java程序员陷入其中)。但是,区分&#34;对价值有用&#34;和&#34;对副作用有用&#34;因为这种区别不是以编译器易于理解或开发人员表示的方式捕获的。有些语言非常擅长区分,就像CAML系列中的语言一样。
答案 1 :(得分:0)
调用
names.OrderBy(x => x);
而不先将其分配给变量是没用的。
仅仅因为某些东西是无用的并不意味着编译器会(或应该)拒绝它。
您不仅可以使用LINQ查询,还可以使用任何方法来证明您的观点。
就像你有一些列表一样,然后你做list.IndexOf(-1);
。你没有将这个值存储在任何东西中,所以对于所有意图和目的来说它都是无用的,但它仍然是一个有效的陈述。