Я хочу сказать:
public void Problem(Guid optional = Guid.Empty)
{
}
Но компилятор жалуется, что Guid.Empty не является постоянной времени компиляции.
Поскольку я не хочу менять API, я не могу использовать:
Nullable<Guid>
Я хочу сказать:
public void Problem(Guid optional = Guid.Empty)
{
}
Но компилятор жалуется, что Guid.Empty не является постоянной времени компиляции.
Поскольку я не хочу менять API, я не могу использовать:
Nullable<Guid>
new Guid()
isnteadpublic void Problem(Guid optional = new Guid())
{
// when called without parameters this will be true
var guidIsEmpty = optional == Guid.Empty;
}
default(Guid)
default(Guid)
также будет работать точно как new Guid()
.
Потому что Guid является типом значения, а не ссылочным типом, поэтому default(Guid)
не равен null
, например, он равен вызову конструктора по умолчанию.
Это означает, что это:
public void Problem(Guid optional = default(Guid))
{
// when called without parameters this will be true
var guidIsEmpty = optional == Guid.Empty;
}
Это точно так же, как и исходный пример.
Guid.Empty
?Причина, по которой вы получаете ошибку, состоит в том, что Empty
определяется как:
public static readonly Guid 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
или чем-то определенным с использованием функции С#, которая делает значение известным во время компиляции, например default(Guid)
или new Guid()
(что решено во время компиляции для struct
, поскольку вы не можете изменить конструктор struct
в коде).
Пока вы можете легко предоставить default
или new
, вы не можете предоставить const
(потому что это не примитивный тип или enum
, как объяснялось выше). Поэтому, опять же, не говоря, что для необязательного параметра требуется константа, но известное значение компилятора.
Guid.Empty
эквивалентен new Guid()
, что эквивалентно default(Guid)
. Таким образом, вы можете использовать:
public void Problem(Guid optional = default(Guid))
или
public void Problem(Guid optional = new Guid())
Обратите внимание, что значение new Foo()
применимо только тогда, когда:
Foo
- тип значенияДругими словами, когда компилятор знает, что это действительно просто значение по умолчанию для типа:)
(Интересно, что я 99.9% уверен, что он не будет вызывать какой-либо пользовательский конструктор new Foo()
, который вы, возможно, создали. Вы не можете создать такой конструктор в типе значений в С#, но вы можете сделать это в IL.)
Вы можете использовать опцию default(Foo)
для любого типа.
Вы не можете использовать:
default ( Guid )
?
Принятый ответ не работает в ASP.NET MVC и вызывает эту ошибку во время выполнения:
[ArgumentException: The parameters dictionary contains a null entry for parameter 'optional' of non-nullable type 'System.Guid' for method 'System.Web.Mvc.ActionResult Problem(System.Guid)' ....
Вместо этого вы можете сделать следующее:
public void Problem(Guid? optional)
{
if (optional == null)
{
optional = new Guid();
}
}
Компилятор вполне корректен; Guid.Empty
не является константой времени компиляции. Вы можете попробовать перегрузить метод следующим образом:
public void Problem()
{
Problem(Guid.Empty);
}