Как я могу по умолчанию использовать параметр Guid.Пусто в 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
s, поскольку вы не можете изменить 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.)
можно использовать на любой тип.
принятый ответ не работает в 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);
}