Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 冗余代码是在编译器中管理还是每次都执行?_C#_Asp.net_Asp.net Core - Fatal编程技术网

C# 冗余代码是在编译器中管理还是每次都执行?

C# 冗余代码是在编译器中管理还是每次都执行?,c#,asp.net,asp.net-core,C#,Asp.net,Asp.net Core,我正在优化一个旧代码(并将一些代码转移到一个新的项目中),我偶然发现了这段代码 if (typeList.FirstOrDefault()?.typeId == Constants.OpenTextTypeId) generatedTextStrBuilder.Append("Empty"); else if (typeList.FirstOrDefault()?.typeId == Constants.OutSideId) generatedTextStrBuilder.App

我正在优化一个旧代码(并将一些代码转移到一个新的项目中),我偶然发现了这段代码

if (typeList.FirstOrDefault()?.typeId == Constants.OpenTextTypeId)
    generatedTextStrBuilder.Append("Empty");
else if (typeList.FirstOrDefault()?.typeId == Constants.OutSideId)
    generatedTextStrBuilder.Append($" [{ typeList.First().typeName }] ");
else if (Constants.typeListOfReview.Contains(typeList.FirstOrDefault()?.typeId))
    generatedTextStrBuilder.Append($"*[{ typeList.FirstOrDefault()?.typeName }]*");
else
    generatedTextStrBuilder.Append($"_[{ typeList.FirstOrDefault()?.typeName }]_");
正如您在代码中看到的那样
typeList.FirstOrDefault()?.typeId
在每个条件中写入一次

问题是:编译器是管理这种类型的冗余,还是每次都执行它


如果编译器这样做了,它是否只在这个方法中管理它?

编译器必须每次发出调用
FirstOrDefault()
的代码。毕竟,以下任何一项都可能是正确的:

  • typeList
    引用的对象可能在
    if
    else if
    之间更改,例如在多线程应用程序中
  • FirstOrDefault
    的输出可能取决于某些外部状态,而不仅仅取决于输入,因此多个调用可能返回不同的内容
  • FirstOrDefault
    可能有副作用
仔细想想,编译器删除“冗余”代码的唯一方法是

  • typeList
    是不可变对象的不可变集合,每次都以相同的顺序返回项目
  • FirstOrDefault
    是一个纯函数,即它只依赖于输入,没有副作用,并且
  • typeId
    如果基础对象没有更改,则返回相同的值

(这个条件列表很可能不完整,可能比这个简单列表所显示的要复杂得多)

是的。每次都会执行,因为

例如,当我构建一个小项目(发布构建)时

int i = 0;
Console.WriteL("Hello world !")
并对其进行编译并生成exe文件


然后我通过.Net Reflection反编译了它,我发现冗余行(
int i=0
)仍然存在于编译后的代码中。

我不希望编译器缓存结果-FirstOrDefault是确定的,除非底层列表在检查分支的条件之间发生变化,但这肯定不是编译器所知道的。您可以很容易地调用IEnumerable上的扩展方法,该方法每次返回一个随机项,而不是第一个。通过创建自己的扩展方法,您可以很容易地验证这一点

公共静态类MyEnumerableExtensions
{
公共静态T MyFirstOrDefault(此IEnumerable可枚举)
{
WriteLine(“正在执行FirstOrDefault()”;
返回可枚举的.FirstOrDefault();
}
}
公共课程
{
公共类类型
{
公共int类型ID{get;set;}
}
公共静态void Main(字符串[]args)
{
var typeList=新列表
{
新类型{TypeId=4}
};
if(typeList.MyFirstOrDefault().TypeId==1)
{
控制台。写入线(“1”);
}
else if(typeList.MyFirstOrDefault().TypeId==2)
{
控制台。写入线(“2”);
}
else if(typeList.MyFirstOrDefault().TypeId==3)
{
控制台。写入线(“3”);
}
其他的
{
控制台。写入线(“其他”);
}
}
}
控制台输出为

Executing FirstOrDefault()
Executing FirstOrDefault()
Executing FirstOrDefault()
other

我当然会将返回typeId的表达式提取到变量中,这也有利于可读性。

这个实验并不能证明这个问题的前提。首先,问题是关于函数调用,而不是关于本地未使用的变量。第二,如果启用了适当的优化,您的代码行将被完全删除,因为编译器可以推断它不会产生任何影响。我也不会。我的观点是您所做的,不能证明你的答案回答了OP的问题。@CodeCaster我尊重你。我同意你的观点并接受你的想法。是的,这可能不能证明问题的概念。:“当启用
优化
选项时,C#编译器会删除未使用的局部变量。”编译器不会执行你的代码,这确实是CLR的工作。编译器将您的代码转换为IL代码,然后由CLR运行。在这方面,每次使用
FirstOrDefault
都会产生一组单独的IL指令,因此,是的,相同的代码将有效地重复运行。