如何在C#中将参数默认为Guid.Empty?

时间:2011-02-25 13:47:54

标签: c# c#-4.0 optional-parameters

我想说:

public void Problem(Guid optional = Guid.Empty)
{
}

但编译器抱怨Guid.Empty不是编译时常量。

由于我不想更改API,我无法使用:

 Nullable<Guid>

5 个答案:

答案 0 :(得分:200)

解决方案

您可以使用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)或{{1 (在new Guid() s的编译时决定,因为你无法修改代码中的struct构造函数。)

虽然您可以轻松提供structdefault,但您无法提供new(因为它不是原始类型或const,如上所述)。所以,再说一遍,并不是说可选参数本身需要一个常量,而是编译器已知的值。

答案 1 :(得分:148)

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)选项。

答案 2 :(得分:17)

你不能用:

default ( Guid )

答案 3 :(得分:7)

接受的答案在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();
    }
}

答案 4 :(得分:4)

编译器非常正确; Guid.Empty不是编译时常量。您可以尝试使用这样的方法重载:

public void Problem()
{
    Problem(Guid.Empty);
}