如何在C#中默认参数Guid.Empty?
我想说:
public void Problem(Guid optional = Guid.Empty) { }
但编译器抱怨Guid.Empty不是一个编译时间常量。
由于我不想更改API,我不能使用:
Nullable<Guid>
解
你可以使用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是一个值types而不是引用types,所以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;
所以,它是一个variables,而不是一个常量(定义为static readonly而不是const )。 编译器只能将编译器已知的值作为方法参数的默认值(而不是运行时已知的)。
根本原因是你不能有任何struct的const ,不像enum例如。 如果你尝试,它不会编译。
原因再一次是, struct不是一个原始types。
有关.NET中所有基元types的列表,请参阅http://msdn.microsoft.com/zh-CN/library/system.typecode.aspx
(注意enum通常inheritanceint ,这是一个原语)
但new Guid()也不是一个常量!
我并不是说它需要一个常数。 它需要一些可以在编译时决定的东西。 Empty是一个字段,所以它的值在编译时间是不知道的(只在运行时开始)。
在编译时必须知道缺省的参数值,这可能是一个常量值,或者是使用C#特性来定义的,这个特性可以在编译时使值成为已知的,比如default(Guid)或者new Guid()因为你不能修改代码中的struct构造函数)。
虽然您可以轻松地提供default或new ,但不能提供const (因为它不是原始types或enum ,如上所述)。 所以,不要说可选参数本身需要一个常量,但是编译器已知的值。
Guid.Empty相当于new Guid() ,相当于default(Guid) 。 所以你可以使用:
public void Problem(Guid optional = default(Guid))
要么
public void Problem(Guid optional = new Guid())
请注意, new Foo()值仅适用于以下情况:
- 你真的调用了无参数的构造函数
-
Foo是一个值types
换句话说,当编译器知道它实际上只是types的默认值:)
(有趣的是,我99.9%确定它不会调用你可能创build的任何自定义的new Foo()构造函数,你不能在C#中创build这样的构造函数,但是你可以在IL中创build。
您可以使用任何types的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); }