Как я могу по умолчанию параметр Guid.Empty в C#?
Я хочу сказать:
public void Problem(Guid optional = Guid.Empty)
{
}
Но компилятор жалуется, что Guid.Empty не является постоянной времени компиляции.
Поскольку я не хочу менять API, я не могу использовать:
Nullable<Guid>
5 ответов
Решение
Ты можешь использовать new Guid()
вместо
public 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
значение, или что-то определенное с помощью функции C#, которая делает значение известным во время компиляции, например 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()
конструктор, который вы, возможно, создали. Вы не можете создать такой конструктор в типе значения в C#, но вы можете сделать это в IL.)
Вы можете использовать default(Foo)
вариант для любого типа.
Принятый ответ не работает в 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);
}