c#编译器是否从循环中调用的方法中提升变量声明?
本文关键字:变量 声明 方法 调用 是否 编译器 循环 | 更新日期: 2023-09-27 18:10:22
我有一个从for
循环中调用助手方法的方法。helper方法包含一个相对昂贵的变量声明和定义,其中涉及反射(见下文)。我想知道是否可以指望编译器内联方法调用并将声明和定义从循环中提升出来,或者我是否需要重构方法以保证定义语句不会在每次迭代中执行。
private class1[] BuildClass1ArrayFromTestData()
{
var class1Count = int.Parse(testContextInstance.DataRow["class1[]"].ToString());
var class1s = new List<class1>(class1Count);
for (var c = 0; c < class1Count; c++)
{
class1s.Add(BuildClass1FromTestData(string.Format("class1[{0}]", c)));
}
return class1s.ToArray();
}
private class1 BuildClass1FromTestData(string testContextName)
{
DataColumnCollection columns = testContextInstance.DataRow.Table.Columns;
var class1Fields = typeof(class1).GetFields();
var class1Object = new class1();
foreach (var field in class1Fields)
{
var objectContextName = string.Format("{0}.{1}", testContextName, field.Name);
if (!columns.Contains(objectContextName))
continue;
// Assume that all fields are of type "string" for simplicity
field.SetValue(
class1Object,
testContextInstance.DataRow[objectContextName].ToString()
);
}
return class1Object;
}
更新:
为了澄清起见,下面是我设想的替代方案:
private class1[] BuildClass1ArrayFromTestData()
{
var class1Count = int.Parse(testContextInstance.DataRow["class1[]"].ToString());
var class1s = new List<class1>(class1Count);
// Moved from BuildClass1FromTestData()
DataColumnCollection columns = testContextInstance.DataRow.Table.Columns;
var class1Fields = typeof(class1).GetFields();
for (var c = 0; c < class1Count; c++)
{
class1s.Add(BuildClass1FromTestData(string.Format("class1[{0}]", c)), columns, class1Fields);
}
return class1s.ToArray();
}
private class1 BuildClass1FromTestData(string testContextName, DataColumnCollection columns, FieldInfo[] class1Fields)
{
var class1Object = new class1();
foreach (var field in class1Fields)
{
var objectContextName = string.Format("{0}.{1}", testContextName, field.Name);
if (!columns.Contains(objectContextName))
continue;
// Assume that all fields are of type "string" for simplicity
field.SetValue(
class1Object,
testContextInstance.DataRow[objectContextName].ToString()
);
}
return class1Object;
}
c#中没有昂贵的变量声明。事实上,MSIL甚至不区分在循环内部和外部声明的变量,它们都只是方法的局部变量(自然,循环方法中的变量和helper方法中的变量是有区别的)。
初始化可能代价高昂,但将其移出循环将显著改变代码的行为。
编译器不会做这样的事情,因为它不会是一个优化,但它会改变你的代码的意义。一次调用函数与多次调用函数是不一样的,并且编译器只允许在从同一线程观察时进行不会改变程序效果的更改。无法检测函数是否为纯。
作为旁注,编译器甚至不会内联函数调用。这是JIT的工作。