Подтвердить что ты не робот

Что делать с фигурными скобками после выполнения нового оператора С#?

С учетом приведенного ниже кода в чем разница между инициализацией пути 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;
}
4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

Забыв обо всех материалах IL, это всего лишь сокращенная запись. Что вы делаете, так это:

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

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

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

Ответ 6

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

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

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

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

Ответ 7

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

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

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