C# 中如何给 Guid.Empty 设置默认值 ?

我想说:

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

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

因为我不想改变我不能使用的API:

 Nullable
94829 次浏览

你不能用:

default ( Guid )吗?

编译器是相当正确的;Guid.Empty不是编译时常量。你可以尝试这样重载一个方法:

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

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

解决方案

你可以使用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)。编译器只能将编译器已知的值作为方法参数的默认值(而不是仅运行时已知的值)。

根本原因是你不能有任何structconst,不像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构造函数)。

虽然你可以很容易地提供defaultnew,但你不能提供const(因为它不是一个基本类型,也不是上面解释的enum)。所以,再一次,不是说可选参数本身需要一个常量,而是编译器已知的值。

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