为什么没有编译器警告没有分配给变量的LINQ查询

Sla*_*jic 0 c# linq

假设我有一个名单names:

List<string> names = new List<string> { "Mike", "Steve", "Alan", "John" };
Run Code Online (Sandbox Code Playgroud)

现在,如果我List<T>.Sort在列表中使用该方法names:

names.Sort();
Run Code Online (Sandbox Code Playgroud)

该列表names将被排序:

"艾伦","约翰","迈克","史蒂夫"

假设我使用LINQ OrderBy而不是Sort初始列表names:

names.OrderBy(x => x);
Run Code Online (Sandbox Code Playgroud)

初始列表names不会被排序:

"迈克","史蒂夫","艾伦","约翰"

我知道如果我想names用LINQ 对列表进行排序OrderBy我必须将查询分配给变量:

var orderedNames = names.OrderBy(x => x); 
Run Code Online (Sandbox Code Playgroud)

初始列表names保持未排序,但orderedNames将保存初始列表的排序名称:

"艾伦","约翰","迈克","史蒂夫"

我很好奇为什么没有编译器警告没有分配给变量的LINQ查询,因为调用names.OrderBy(x => x);而不首先将它分配给变量是没用的.

Eri*_*ert 10

为什么没有编译器警告没有分配给变量的LINQ查询

这是一个功能.默认情况下不存在功能,必须将其删除.需要考虑,设计,指定,实施,测试,记录和发送功能.

所有这些事情都需要发生才能让你拥有这个功能.他们都没有发生.因此,没有任何功能.

如果您想要实现该功能,请选择它.编译器是开源的.如果你想提倡其他人实施它,那就去吧; 设计过程也是公开的.

如果你要实现它,而你在它,你也可以寻找的东西来电来样TrimToLower等等,对字符串,从未使用.

现在,请注意"未分配给变量"是不够的.例如:

names.OrderBy(whatever).ToList().ForEach(whatever);
Run Code Online (Sandbox Code Playgroud)

不为变量赋值,但你不想对此发出警告.同样

Foo(names.OrderBy(whatever))
Run Code Online (Sandbox Code Playgroud)

通过调用分配给变量(参数),而不是赋值.

同样

x = y ? names.OrderBy(whatever) : whatever;
Run Code Online (Sandbox Code Playgroud)

不直接分配,但仍使用该值. 要非常小心.编译器已经有一个检测器可以正确地确定表达式是否用于其值,所以研究一下.

现在,也许你的问题是"有什么困难或其他'点反对'做这样的功能?"

问题总是误报.误报是代码正常工作的场景,它可以像开发人员想要的那样工作,代码可以被读者理解,并且它仍然会收到警告.最好的误报让开发人员烦恼,但情况变得更糟.误报可能破坏对编译器的信任,并且它们可能导致人们将工作代码更改为不警告的错误代码.

让我们来看一个微妙的案例.假设我们有这样可怕的东西:

giraffes.Select(g => { g.Feed(); return 1; }).ToList();
Run Code Online (Sandbox Code Playgroud)

这是可怕的代码.但警告不能像"包含查询的表达式语句无用",因为这是误报.用户在这里做了非常非常错误的事情,但他们没有做出无用的查询; 这个查询提供了所有的长颈鹿.

这里的错误是编写一个仅对其副作用有用的查询.查询不应该有副作用,这是一种非常糟糕的写作方式foreach(var g in giraffes) g.Feed();

警告不仅要准确 99.99%的时间,他们必须尽可能确定真正的问题.这是一个超级难题,编译器团队已经有了足够的问题.

这里有一个教训,那就是:考虑一下在设计语言时你想要阻止的不良做法.C#非常擅长防止C和C++程序员陷入的许多经典坏习惯.(还有一些Java程序员陷入其中).但是,区分"对价值有用"和"对副作用有用"是不好的,因为这种区别不是以易于编制者理解或开发人员代表的方式捕获的.有些语言非常擅长区分,就像CAML系列中的语言一样.