Я хочу сказать:
public void Problem(Guid optional = Guid.Empty)
{
}
Но компилятор жалуется, что Guid.Empty не является постоянной времени компиляции.
Поскольку я не хочу менять API, я не могу использовать:
Nullable<Guid>
c#
c#-4.0
optional-parameters
Ян Рингроз
источник
источник
Nullable<Guid> optional = null
(или, более кратко,Guid? optional = null
)? Любые Руководства, переданные ему в настоящее время, будут принудительно выполняться без каких-либо изменений кода.Ответы:
Решение
Вы можете использовать
new Guid()
вместоВы также можете использовать
default(Guid)
default(Guid)
и будет работать точно так жеnew Guid()
.Поскольку Guid является типом значения, а не ссылочным типом, то
default(Guid)
есть не равен,null
например, вместо этого он равен вызову конструктора по умолчанию.Что означает, что это:
Это точно так же, как оригинальный пример.
объяснение
Почему не
Guid.Empty
работает?Причина, по которой вы получаете ошибку, заключается в том, что
Empty
она определяется как:Таким образом, это является переменной, не является постоянным (определяется как
static readonly
не такconst
). Компилятор может иметь только значения, известные компилятору, в качестве значений параметров метода по умолчанию (не известно только во время выполнения).Основная причина в том, что вы не можете иметь
const
ничегоstruct
, в отличие от,enum
например. Если вы попробуете это, он не скомпилируется.Причина еще раз в том, что
struct
это не примитивный тип.Список всех примитивных типов в .NET см. По адресу http://msdn.microsoft.com/en-gb/library/system.typecode.aspx
(обратите внимание, что
enum
обычно наследуетсяint
, что является примитивом)Но
new Guid()
тоже не константа!Я не говорю, что нужна постоянная. Нужно что-то, что можно решить во время компиляции.
Empty
это поле, поэтому его значение неизвестно во время компиляции (только в самом начале времени выполнения).Значение параметра по умолчанию должно быть известно во время компиляции, которое может быть
const
значением или определенным с помощью функции C #, которая делает значение известным во время компиляции, напримерdefault(Guid)
илиnew Guid()
(которое определяется во время компиляции дляstruct
s, поскольку вы не можете изменитьstruct
конструктор в код).Хотя вы можете предоставить
default
илиnew
легко, вы не можете предоставитьconst
(потому что это не примитивный тип илиenum
как описано выше). Итак, опять же, не говоря о том, что самому необязательному параметру нужна постоянная, но известная компилятору величина.источник
new Guid()
это не постоянное выражение. Спецификация C # довольно четко определяет, что разрешено, включая, но не ограничиваясь, константы (Просто чтобы прояснить, это эффективно является константой времени компиляции, а не «константным выражением» в терминах спецификации C #).default
настоящее время :)Guid.Empty
эквивалентноnew Guid()
, что эквивалентноdefault(Guid)
. Таким образом, вы можете использовать:или
Обратите внимание, что
new Foo()
значение применимо только когда:Foo
это тип значенияДругими словами, когда компилятор знает, что это действительно просто значение по умолчанию для типа :)
(Интересно, что я на 99,9% уверен, что он не вызовет никакого
new Foo()
созданного вами пользовательского конструктора. Вы не можете создать такой конструктор в типе значения в C #, но вы можете сделать это в IL.)Вы можете использовать эту
default(Foo)
опцию для любого типа.источник
Nullable<Guid>
потенциально.Вы не можете использовать:
default ( Guid )
?источник
Operator '??' cannot be applied to operands of type 'System.Guid' and 'System.Guid'
Принятый ответ не работает в ASP.NET MVC и вызывает эту ошибку во время выполнения:
Вместо этого вы можете сделать следующее:
источник
Компилятор вполне корректен;
Guid.Empty
не является константой времени компиляции. Вы можете попробовать перегрузить метод следующим образом:источник
Guid x = default(Guid)
в качестве решения, помните, что добавление другой перегрузки функции не усложняет API больше, чем добавление дополнительного аргумента. Это действительно то, что необязательный аргумент делает в любом случае.