Answers:
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
not const
)。编译器只能将编译器已知的值用作方法参数的默认值(不是仅运行时已知的)。
根本原因是您不能拥有const
any 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
s的编译时确定的,因为您不能在s中修改struct
构造函数。码)。
尽管可以提供default
或new
很容易提供,但不能提供const
(因为它不是原始类型或enum
如上所述)。因此,同样,不是说可选参数本身需要一个常量,而是编译器已知的值。
new Guid()
例如,不是常数表达式。C#规范非常清楚地定义了允许的内容,包括但不限于常量。(需要明确的是,它实际上是一个编译时间常数,而不是C#规范术语中的“常数表达式”)。
default
现在只能使用:)
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)
选项用于任何类型。
Nullable<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);
}
Guid x = default(Guid)
作为解决方案,但请记住,添加另一个函数重载不会使API变得比添加可选参数更复杂。无论如何,这确实是一个可选参数。