I wish to say:
public void Problem(Guid开发者_如何学Go optional = Guid.Empty)
{
}
But the compiler complains that Guid.Empty is not a compile time constant.
As I don’t wish to change the API I can’t use:
Nullable<Guid>
Solution
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)
also will work exactly as new Guid()
.
Because Guid is a value type not reference type, so, default(Guid)
is not equal to null
for example, instead, it's equal to calling default constructor.
Which means that this:
public void Problem(Guid optional = default(Guid))
{
// when called without parameters this will be true
var guidIsEmpty = optional == Guid.Empty;
}
It's exactly the same as the original example.
Explanation
Why didn't Guid.Empty
work?
The reason you are getting the error is because Empty
is defined as:
public static readonly Guid Empty;
So, it is a variable, not a constant (defined as static readonly
not as const
). Compiler can only have compiler-known values as method parameters default values (not runtime-only-known).
The root cause is that you cannot have a const
of any struct
, unlike enum
for example. If you try it, it will not compile.
The reason once more is that struct
is not a primitive type.
For a list of all primitive types in .NET see http://msdn.microsoft.com/en-gb/library/system.typecode.aspx
(note that enum
usually inherits int
, which is a primitive)
But new Guid()
is not a constant too!
I'm not saying it needs a constant. It needs something that can be decided in compile time. Empty
is a field, so, it's value is not known in compile time (only at very beginning of run time).
Default parameter value must be known at compile-time, which may be a const
value, or something defined using a C# feature that makes value known at compile time, like default(Guid)
or new Guid()
(which is decided at compile time for struct
s as you cannot modify the struct
constructor in code).
While you can provide default
or new
easily, you cannot provide a const
(because it's not a primitive type or an enum
as explained above). So, again, not saying that optional parameter itself needs a constant, but compiler known value.
Guid.Empty
is equivalent to new Guid()
, which is equivalent to default(Guid)
. So you can use:
public void Problem(Guid optional = default(Guid))
or
public void Problem(Guid optional = new Guid())
Note that the new Foo()
value is only applicable when:
- You're really calling the parameterless constructor
Foo
is a value type
In other words, when the compiler knows it's really just the default value for the type :)
(Interestingly, I'm 99.9% sure it won't call any custom new Foo()
constructor you may have created. You can't create such a constructor in a value type in C#, but you can do so in IL.)
You can use the default(Foo)
option for any type.
Can't you use:
default ( Guid )
?
The accepted answer does not work in ASP.NET MVC, and cause this run-time error:
[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)' ....
Instead, you may do the following:
public void Problem(Guid? optional)
{
if (optional == null)
{
optional = new Guid();
}
}
The compiler is quite correct; Guid.Empty
is not a compile-time constant. You can try making a method overload like this:
public void Problem()
{
Problem(Guid.Empty);
}
精彩评论