如何在C#中将参数默认为Guid.Empty?

Ian*_*ose 171 c# optional-parameters c#-4.0

我想说:

public void Problem(Guid optional = Guid.Empty)
{
}
Run Code Online (Sandbox Code Playgroud)

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

由于我不想更改API,我无法使用:

 Nullable<Guid>
Run Code Online (Sandbox Code Playgroud)

Mel*_*igy 217

你可以new Guid()改用

public void Problem(Guid optional = new Guid())
{
  // when called without parameters this will be true
  var guidIsEmpty = optional == Guid.Empty;
}
Run Code Online (Sandbox Code Playgroud)

你也可以使用 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;
}
Run Code Online (Sandbox Code Playgroud)

它与原始示例完全相同.

说明

为什么不Guid.Empty工作?

您收到错误的原因是因为Empty定义为:

public static readonly Guid Empty;
Run Code Online (Sandbox Code Playgroud)

所以,它是一个变量,而不是一个常量(定义为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)或者new Guid()(在编译时为structs 决定,因为你无法修改struct构造函数)码).

虽然您可以提供defaultnew轻松提供,但您不能提供const(因为它不是原始类型或enum如上所述).所以,再说一遍,并不是说可选参数本身需要一个常量,而是编译器已知值.

  • 好吧,它不需要正常的常量表达式 - 例如,新的Guid()`不是常量表达式.C#规范非常清楚地定义了允许的内容,*包括*但不限于常量.(为了清楚起见,它实际上*是*编译时常量,而不是C#规范中的"常量表达式"). (5认同)
  • 在我的回复中阅读部分**说明**.添加回答这部分. (3认同)
  • 现在你只能使用“default”:) (2认同)

Jon*_*eet 149

Guid.Empty相当于new Guid(),相当于default(Guid).所以你可以使用:

public void Problem(Guid optional = default(Guid))
Run Code Online (Sandbox Code Playgroud)

要么

public void Problem(Guid optional = new Guid())
Run Code Online (Sandbox Code Playgroud)

请注意,该new Foo()适用于:

  • 你真的在调用无参数构造函数
  • Foo 是一种值类型

换句话说,当编译器知道它实际上只是类型的默认值:)

(有趣的是,我99.9%肯定它不会调用new Foo()你可能创建的任何自定义构造函数.你不能在C#中的值类型中创建这样的构造函数,但是你可以在IL中这样做.)

您可以将该default(Foo)选项用于任何类型.

  • @Ian Ringrose:老实说,我认为编译器一般不应该有类型特定的消息. (4认同)
  • 每次在PHP中调用方法时,将参数设置为默认为新对象都会创建一个新对象; 但只在Python中为*整个程序*创建一个对象.实际上,我认为这是[很少有Python的设计缺陷]之一(http://stackoverflow.com/questions/146329/what-is-the-worst-gotcha-youve-experienced/147877#147877).我有点高兴C#(和VB.Net)通过简单地禁止默认参数中的新对象来避免这个问题......虽然有时候这种能力在PHP中非常好用. (2认同)

Nic*_*ick 18

你不能用:

default ( Guid )

  • 对不起,我不是故意的?作为一个操作员,但作为一个强调的问号 - 我会编辑! (4认同)

Maj*_*jix 8

接受的答案在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)' ....
Run Code Online (Sandbox Code Playgroud)

相反,您可以执行以下操作:

public void Problem(Guid? optional)
{
    if (optional == null)
    {
        optional = new Guid();
    }
}
Run Code Online (Sandbox Code Playgroud)