tags:

views:

305

answers:

8

Given the code below, what is the difference between the way position0 is initialized and the way position1 is initialized? Are they equivalent? If not, what is the difference.

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;
}
A: 

These are fully equivalent. The compiler actually just transforms the first version into the second one.

The only difference between the two is that with the first, you can do nice thins, like pass the initialized version to a method:

DoSomethingWithPoint(new Position() { x=3, y=4 });

This is a lot more lines of code than the second initialization example.

Pieter
+3  A: 

Your two code samples will generate identical IL. (At least in Release builds)

SLaks
A: 

the curly braces {} do initialise the variables of the struct Position. it's just shorter

Oops
+15  A: 

Object and collection initializers, used to initialize fields on an object.

http://msdn.microsoft.com/en-us/library/bb384062.aspx

They produce nearly equivalent IL. Jon Skeet has the answer on what is really going on.

Joshua Rodgers
+1 MSDN reference
Rice Flour Cookies
*Jon Skeet has the answer on what is really going on.* Actually, when you don't feel like writing a lengthy post, you can simply end any post with that line, and have Jon Skeet fill in the details. And actually, by the time you click "Post your answer", Jon's post will already be there.
Groo
Much truth to that. Posted my answer... saw his answer, edited it to point out his answer.
Joshua Rodgers
Jon Skeet seems to answer every question on this site :) I can't wait to read his new book (if it ever actually gets released)
Bryan
+1  A: 

That is an object initialiser, and simply allows you to assign values in a single expression. Most importantly, this also works inside LINQ an for anonymous types (otherwise immutable). There is also a similar collection initialiser syntax for addi items to new collections.

Note that there is a subtle timing issue that can be useful; with initialisers the assignments/adds all happen before the variable is assigned, which can help stop other threads seeing an incomplete object. You would otherwise need an additional variable to achieve the same result.

Marc Gravell
Joshua and Slaks posted that both ways of initializing `Position` produce equivalent IL. Are you saying that with anonymous types, I would get a different result?
Rice Flour Cookies
@rice - yes: only one of them would compile :)
Marc Gravell
A: 

They are equivalent, apart from one being easier to read than the other one.

Also consider the case when you want to pass the new object along to somewhere else:

var aList = new List<Position>();
aList.Add( new Position() { x=3, y=4 } );
danbystrom
+10  A: 

They are not quite equivalent - at least not in the general case. The code using an object initializer is closer to this:

Position tmp = new Position();
tmp.x = 3;
tmp.y = 4;
Position position1 = tmp;

In other words, the assignment to the variable only occurs after the properties have been set. Now in the case where you're declaring a new local variable, that doesn't actually matter, and the compiler may well optimize to your first form. But logically, it does matter. Consider:

Position p1 = new Position { x = 10, y = 20 };

p1 = new Position { x = p1.y, y = p1.x };

If that did the assignment to p1 first, you'd end up with 0 for both p1.x and p1.y. Whereas that's actually equivalent to:

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;

EDIT: I've just realised that you're using a struct rather than a class. That may make some subtle differences... but you almost certainly shouldn't be using a mutable struct to start with :)

Jon Skeet
A: 

Forgetting about all the IL stuff, it is just shorthand notation. What you are doing is this:

a. In one case you are explicitly using the default constructor and then setting the two properties.

b. In the other, you are using the new intializer syntax which implicitly makes the compiler do what you did in case a.

IL subtelties notwithstanding, they will achieve the same thing for you.

awrigley