我想说:
public void Problem(Guid optional = Guid.Empty)
{
}
但编译器抱怨Guid.Empty不是编译时常量。
由于我不想更改API,我无法使用:
Nullable<Guid>
答案 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
构造函数。)
虽然您可以轻松提供struct
或default
,但您无法提供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);
}