根据下面的代码,初始化position0
的方式和初始化position1
的方式之间有什么区别?它们是等价的吗?如果没有,有什么区别?
class Program
{
static void Main(string[] args)
{
Position position0 = new Position() { x=3, y=4 };
Position position1 = new Position();
position1.x = 3;
position1.y = 4;
}
}
struct Position
{
public int x, y;
}
答案 0 :(得分:58)
它们不是相当等效 - 至少在一般情况下不是这样。使用对象初始值设定项的代码更接近于此:
Position tmp = new Position();
tmp.x = 3;
tmp.y = 4;
Position position1 = tmp;
换句话说,只有设置了属性后才能对变量赋值。现在,在您声明一个新的局部变量的情况下,这实际上并不重要,编译器可能会优化到您的第一个表单。但从逻辑上讲,它确实很重要。考虑:
Position p1 = new Position { x = 10, y = 20 };
p1 = new Position { x = p1.y, y = p1.x };
如果完成了p1
的分配,则p1.x
和p1.y
的结果为0。而那实际上相当于:
Position tmp = new Position();
tmp.x = 10;
tmp.y = 20;
Position p1 = tmp;
tmp = new Position();
tmp.x = p1.y; // 20
tmp.y = p1.x; // 10
p1 = tmp;
编辑:我刚刚意识到你使用的是结构而不是类。这可能会产生一些微妙的差异......但你几乎肯定不应该使用一个可变的结构来开始:)
答案 1 :(得分:45)
对象和集合初始值设定项,用于初始化对象上的字段。
http://msdn.microsoft.com/en-us/library/bb384062.aspx
他们产生几乎等效的IL。 Jon Skeet对正在发生的事情有了答案。
答案 2 :(得分:7)
这是一个对象初始化器,只是允许您在单个表达式中指定值。最重要的是,这也适用于LINQ和匿名类型(否则是不可变的)。对于新集合,addi项目也有类似的集合初始化语法。
请注意,有一个微妙的时间问题可能有用;对于初始化者,分配/添加全部在分配变量之前发生,这可以帮助阻止其他线程看到不完整的对象。否则你需要一个额外的变量来实现相同的结果。
答案 3 :(得分:2)
您的两个代码示例将生成相同的IL。 (至少在发布版本中)
答案 4 :(得分:2)
忘记所有IL的东西,它只是简写符号。你在做什么是这样的:
一个。在一种情况下,您明确使用默认构造函数,然后设置两个属性。
湾另一方面,您正在使用新的intializer语法,它隐式地使编译器执行您在执行的操作时执行的操作。
尽管如此,他们会为你做同样的事情。答案 5 :(得分:1)
这些完全相同。编译器实际上只是将第一个版本转换为第二个版本。
两者之间的唯一区别是,对于第一个,你可以做很好的,比如将初始化的版本传递给方法:
DoSomethingWithPoint(new Position() { x=3, y=4 });
这比第二个初始化示例要多得多。
答案 6 :(得分:1)
它们是等同的,除了一个比另一个更容易阅读。
还要考虑将新对象传递到其他地方的情况:
var aList = new List<Position>();
aList.Add( new Position() { x=3, y=4 } );