我正在优化旧代码(并将一些代码转移到新项目中),但偶然发现了这段代码
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
在每种情况下都写入一次
问题是:编译器是管理这种类型的冗余还是每次执行?
如果编译器这样做,它是否仅在此方法内对其进行管理?
答案 0 :(得分:2)
编译器必须发出每次调用function uploadXML(){
let xml = '<thexml_you_got_from_the_export><thexml_you_got_from_the_export/>';
let doc = mxUtils.parseXml(xml);
let codec = new mxCodec(doc);
codec.decode(doc.documentElement, universalGraph.getModel());
let elt = doc.documentElement.firstChild;
let cells = [];
while (elt != null)
{
let cell = codec.decode(elt)
if(cell != undefined){
if(cell.id != undefined && cell.parent != undefined && (cell.id == cell.parent)){
elt = elt.nextSibling;
continue;
}
cells.push(cell);
}
elt = elt.nextSibling;
}
universalGraph.addCells(cells);
}
的代码。毕竟,以下任何一项都可能成立:
FirstOrDefault()
所引用的对象可能在typeList
和if
之间变化,例如在多线程应用程序中。else if
的输出可能取决于某些外部状态,而不仅取决于输入,因此多个调用可能返回不同的结果。FirstOrDefault
可能会有副作用。如果考虑到这一点,编译器删除“冗余”代码的唯一方法是if
FirstOrDefault
是不可变对象的不可变集合,每次都会以相同的顺序返回项目。typeList
是一个纯函数,即它仅取决于输入并且没有副作用,并且FirstOrDefault
将返回相同的值。(此条件列表很可能不完整,并且可能比此简单列表所暗示的要复杂得多)
答案 1 :(得分:1)
我不希望编译器缓存结果-FirstOrDefault是确定性的,除非底层列表在检查分支条件之间发生变化,但这当然不是编译器所了解的。您可能已经很容易在IEnumerable上调用了扩展方法,该方法每次都返回一个随机项而不是第一个项。您可以通过创建自己的扩展方法(类似于以下内容)轻松验证这一点...
public static class MyEnumerableExtensions
{
public static T MyFirstOrDefault<T>(this IEnumerable<T> enumerable)
{
Console.WriteLine("Executing FirstOrDefault()");
return enumerable.FirstOrDefault();
}
}
public class Program
{
public class Type
{
public int TypeId { get; set; }
}
public static void Main(string[] args)
{
var typeList = new List<Type>
{
new Type { TypeId = 4 }
};
if (typeList.MyFirstOrDefault().TypeId == 1)
{
Console.WriteLine("1");
}
else if (typeList.MyFirstOrDefault().TypeId == 2)
{
Console.WriteLine("2");
}
else if (typeList.MyFirstOrDefault().TypeId == 3)
{
Console.WriteLine("3");
}
else
{
Console.WriteLine("other");
}
}
}
控制台输出为
Executing FirstOrDefault()
Executing FirstOrDefault()
Executing FirstOrDefault()
other
我当然会提取将typeId返回到变量中的表达式-这也有利于提高可读性。
答案 2 :(得分:0)
是的。因为
,它将每次执行例如,当我构建一个小项目(RELEASE构建)时
int i = 0;
Console.WriteL("Hello world !")
编译并生成exe文件
然后我通过 .Net Reflection 对其进行了反编译,并且我发现在已编译的代码中仍然存在冗余行(int i = 0
)。