Как я могу по умолчанию использовать параметр 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() (которая решается во время компиляции для structs, поскольку вы не можете изменить 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 ( 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);
}