C # struct new StructType () против по умолчанию (StructType) - PullRequest
52 голосов
/ 12 февраля 2011

Скажи, что у меня есть структура

public struct Foo
{
    ...
}

Есть ли разница между

Foo foo = new Foo();

и

Foo foo = default(Foo);

Ответы [ 5 ]

70 голосов
/ 12 февраля 2011

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

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

static T MakeDefault<T>()
{
    return default(T); // legal
    // return new T(); // illegal
}
17 голосов
/ 12 февраля 2011

Нет, оба выражения приведут к одинаковому точному результату.

Поскольку структуры не могут содержать явных конструкторов без параметров (то есть вы не можете определить их самостоятельно), конструктор по умолчанию предоставит вам версию структуры со всеми значениями, обнуленными.Это то же поведение, которое дает вам default.

14 голосов
/ 12 февраля 2011

Для типов значений, варианты, практически говоря, эквивалентны.

Однако я был заинтригован эмпирическим исследованием Джона Скита , в котором «инструкции»привести к вызову конструктора по умолчанию без параметров, если он указан в CIL (вы не можете сделать это в C #, потому что он не позволяет вам).Среди прочего он опробовал default(T) и new T(), где T - параметр типа.Они оказались эквивалентными;ни один из них, казалось, не вызывал конструктор.

Но один случай (кажется), который он не пробовал, был default(Foo), где Foo - фактический тип структуры.

Так что явзял его код для взломанной структуры и попробовал это для себя.


Оказывается, что default (Foo) не вызывает конструктор, тогда как new Foo () на самом делеdo.

Использование типа структуры Oddity, который задает конструктор без параметров:

При отключенной оптимизации , метод:

private void CallDefault()
{
    Oddity a = default(Oddity);
}

производит CIL (без nop с, ret с и т. Д.):

L_0001: ldloca.s a
L_0003: initobj [Oddity]Oddity

, тогда как метод:

private void CallNew()
{
    Oddity b = new Oddity();
}

производит:

L_0001: ldloca.s b
L_0003: call instance void [Oddity]Oddity::.ctor()

При включенных оптимизациях компилятор, по-видимому, оптимизирует все метода CallDefault в бездействие, но сохраняет вызов конструктора в CallNew (для потенциальных побочных эффектов?).

12 голосов
/ 12 февраля 2011

Спецификация языка (§4.1.2 и §5.2) - ваш друг.В частности:

Для переменной тип значения значение по умолчанию совпадает со значением, вычисленным по умолчанию тип-значения Конструктор (§4.1.2).

(Курсив в оригинале.)

Обратите внимание, что это не то же самое для ссылочных типов.

Дляпеременная ссылочного типа, значением по умолчанию является null.

Это существенно отличается от значения, созданного конструктором по умолчанию, если таковой существует.

5 голосов
/ 12 февраля 2011
Ключевое слово

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

T FirstOrDefault(IEnumerable<T> source)
{
    if (...source is empty...) return default(T);
}

Это вернет ноль для ссылочных типов, значение по умолчанию для примитиватипы (0 для чисел, false для bool), по умолчанию инициализированная структура и т. д. *

Когда тип известен во время компиляции, нет смысла использовать default, вместо него можно использовать new Foo()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...