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

问题描述 投票:162回答:5

我想说:

public void Problem(Guid optional = Guid.Empty)
{
}

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

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

 Nullable<Guid>
c# c#-4.0 optional-parameters
5个回答
199
投票

You can use new Guid() instead

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

You can also use 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;
}

它与原始示例完全相同。

说明

Why didn't Guid.Empty work?

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

public static readonly Guid Empty;

所以,它是一个变量,而不是常数(定义为static readonly而不是const)。编译器只能将编译器已知的值作为方法参数的默认值(不仅仅是运行时已知)。

根本原因是你不能拥有任何conststruct,例如enum。如果你尝试它,它将无法编译。

原因再一点是struct不是原始类型。 有关.NET中所有基本类型的列表,请参阅http://msdn.microsoft.com/en-gb/library/system.typecode.aspx (请注意,enum通常继承int,这是一个原始的)

But new Guid() is not a constant too!

我不是说它需要一个常数。它需要一些可以在编译时决定的东西。 Empty是一个字段,因此,它的值在编译时是未知的(仅在运行时的开始时)。

默认参数值必须在编译时知道,这可能是一个const值,或者是使用C#特性定义的,它在编译时使值已知,如default(Guid)new Guid()(在编译时为structs决定,因为您无法修改代码中的struct构造函数)。

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


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)选项用于任何类型。


17
投票

你不能用:

default ( Guid )


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
投票

编译器非常正确; Guid.Empty不是编译时常量。您可以尝试使方法重载如下:

public void Problem()
{
    Problem(Guid.Empty);
}
© www.soinside.com 2019 - 2024. All rights reserved.