对不起标题,很难说。请看我的例子。
GetUser1和GetUser2之间有什么区别吗?
class Program
{
static void Main(string[] args)
{
GetUser1();
GetUser2();
}
private static User GetUser1()
{
return new User
{
Name = "Hello"
};
}
private static User GetUser2()
{
User user = new User
{
Name = "Hello"
};
return user;
}
}
public class User
{
public string Name { get; set; }
}
我的一个朋友说;没有区别 但是我这么说;两种方法之间存在差异。 GetUser2正在创建一个不必要的新对象。并且GetUser2有轻微(非常小的)性能错误,因为您正在创建一个新对象......这是什么真相?我该如何研究这个主题?
更新
非常感谢你的回答...所以我继续问;
如果GetUser1和GetUser2之间没有区别,为什么roslyn会像这样编译代码(link);
private static User GetUser1()
{
return new User {
Name = "Hello"
};
}
答案 0 :(得分:8)
在发布模式中编译时没有区别。如果您在调试模式中查看发出的IL,您会注意到在返回对象之前存储和加载变量的附加stloc/ldloc
instruction形式的细微差别。
如果你看the generated compiler code,你会得到两个相同的结果:
private static void Main(string[] args)
{
Program.GetUser1();
Program.GetUser2();
}
private static User GetUser1()
{
return new User {
Name = "Hello"
};
}
private static User GetUser2()
{
return new User {
Name = "Hello"
};
}
.method private hidebysig static
class User GetUser1 () cil managed
{
// Method begins at RVA 0x2068
// Code size 17 (0x11)
.maxstack 8
IL_0000: newobj instance void User::.ctor()
IL_0005: dup
IL_0006: ldstr "Hello"
IL_000b: callvirt instance void User::set_Name(string)
IL_0010: ret
} // end of method Program::GetUser1
.method private hidebysig static
class User GetUser2 () cil managed
{
// Method begins at RVA 0x2068
// Code size 17 (0x11)
.maxstack 8
IL_0000: newobj instance void User::.ctor()
IL_0005: dup
IL_0006: ldstr "Hello"
IL_000b: callvirt instance void User::set_Name(string)
IL_0010: ret
} // end of method Program::GetUser2
答案 1 :(得分:5)
在没有抖动优化的情况下,调试版本之间存在细微差别,因为冗余没有被删除,因此您可以更轻松地检查调试器中的值。
发布版本将删除它,抖动优化也可以这样做,因此在调试情况之外,两者是相同的。
答案 2 :(得分:2)
两种方法之间存在差异。 GetUser2正在创建一个不必要的新对象。并且GetUser2有轻微(非常小的)性能错误,因为您正在创建一个新对象。
两种方法都在创建一个新对象。使用中间变量(User user
)的方法只增加了:变量,它只是指向同一对象的指针。
一旦方法超出范围,变量就不再存在。
即使在调试模式下,堆栈中另外一个变量的差异也绝对可以忽略不计。