Что делают фигурные скобки после нового оператора C#?


приведенный ниже код, в чем разница между способом 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;
}
7 55

7 ответов:

инициализаторы объектов и коллекций, используемые для инициализации полей объекта.

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

Они производят почти эквивалент IL. У Джона Скита есть ответ на то, что происходит на самом деле.

они не совсем эквивалент - по крайней мере, не в общем случае. Код, использующий инициализатор объекта, ближе к этому:

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первый, вы бы в конечном итоге с 0 для обоих p1.x и p1.y. В то время как это на самом деле эквивалентно:

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: я только что понял, что вы используете структуру, а не класс. Это может сделать некоторые тонкие различия... но вы почти наверняка не должны использовать изменяемую структуру для начала:)

Это инициализатор объекта, и просто позволяет присваивать значения в одном выражении. Самое главное, что это также работает внутри LINQ an для анонимных типов (в противном случае неизменяемых). Существует также аналогичный синтаксис инициализатора коллекции для добавления элементов в новые коллекции.

обратите внимание, что существует тонкая проблема синхронизации, которая может быть полезна; с инициализаторами назначения / добавляет все происходит до переменная назначается, что может помочь остановить другие потоки видя неполный объект. В противном случае вам потребуется дополнительная переменная для достижения того же результата.

ваши два образца кода будут генерировать идентичный IL. (По крайней мере, в релизных сборках)

забывая обо всех Ил вещи, это просто стенографические обозначения. То, что вы делаете это:

а. В одном случае вы явно используя конструктор по умолчанию, а затем установив два свойства.

b. в другом случае вы используете новый синтаксис intializer, который неявно заставляет компилятор делать то, что вы сделали в случае a.

несмотря на тонкости IL, они достигнут того же самого для вас.

они полностью эквивалентны. Компилятор фактически просто преобразует первую версию во вторую.

единственное различие между ними заключается в том, что с первым, вы можете сделать хороший thins, как передать инициализированную версию в метод:

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

это намного больше строк кода, чем во втором примере инициализации.

они эквивалентны, кроме того, что один из них легче читать, чем другой.

также рассмотрим случай, когда вы хотите передать новый объект в другое место:

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