Что делают фигурные скобки после нового оператора 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 ответов:
инициализаторы объектов и коллекций, используемые для инициализации полей объекта.
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 для анонимных типов (в противном случае неизменяемых). Существует также аналогичный синтаксис инициализатора коллекции для добавления элементов в новые коллекции.
обратите внимание, что существует тонкая проблема синхронизации, которая может быть полезна; с инициализаторами назначения / добавляет все происходит до переменная назначается, что может помочь остановить другие потоки видя неполный объект. В противном случае вам потребуется дополнительная переменная для достижения того же результата.
забывая обо всех Ил вещи, это просто стенографические обозначения. То, что вы делаете это:
а. В одном случае вы явно используя конструктор по умолчанию, а затем установив два свойства.
b. в другом случае вы используете новый синтаксис intializer, который неявно заставляет компилятор делать то, что вы сделали в случае a.
несмотря на тонкости IL, они достигнут того же самого для вас.
они полностью эквивалентны. Компилятор фактически просто преобразует первую версию во вторую.
единственное различие между ними заключается в том, что с первым, вы можете сделать хороший thins, как передать инициализированную версию в метод:
DoSomethingWithPoint(new Position() { x=3, y=4 });
это намного больше строк кода, чем во втором примере инициализации.