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指令,因此,是的,相同的代码将有效地重复运行。