我想说:
public void Problem(Guid optional = Guid.Empty)
{
}
但编译器抱怨Guid.Empty不是编译时常量。
由于我不想更改API,我无法使用:
Nullable<Guid>
new Guid()
insteadpublic 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
work?您收到错误的原因是因为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()
is not a constant too!我不是说它需要一个常数。它需要一些可以在编译时决定的东西。 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中这样做。)
您可以将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);
}