创建对象然后返回或直接创建并返回之间有什么区别吗
本文关键字:返回 之间 什么 区别 创建 然后 创建对象 | 更新日期: 2023-09-27 18:25:31
对不起标题,很难说。请看我的例子
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编译这样的代码(链接);
private static User GetUser1()
{
return new User {
Name = "Hello"
};
}
在发布模式编译时没有区别。如果您在调试模式中查看发出的IL,您会注意到在返回对象之前存储和加载变量的附加stloc/ldloc
指令的形式存在细微差异。
如果你查看生成的编译器代码,你会得到两个相同的结果:
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"
};
}
以及为两者生成的IL代码:
.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
在没有抖动优化的调试构建中有一个微小的差异,因为冗余没有被删除,所以您可以更容易地在调试器中检查值。
发布版本将删除它,抖动优化也可以这样做,所以除了调试情况之外,两者是相同的。
两种方法有区别。GetUser2正在创建一个不必要的新对象。GetUser2有一个小(非常小)的性能错误,因为您正在创建一个新对象。
两个方法都在创建一个新对象。使用中间变量(User user
)的方法只添加了一个:一个变量,它只是指向同一对象的指针。
一旦方法超出范围,变量就不存在了。
即使在调试模式下,堆栈上多了一个变量的差异也绝对可以忽略不计。