Как я могу по умолчанию параметр 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) вариант для любого типа.

Вы не можете использовать:

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);
}
Другие вопросы по тегам