Difference between ParameterInfo.IsOptional and ParameterInfo.HasDefaultValue?

Both are alike. From msdn:

ParameterInfo.IsOptional

Gets a value indicating whether this parameter is optional.

This method depends on the optional metadata flag. This flag can be inserted by compilers, but compilers are not required to do this.

This method uses the optional ParameterAttributes scribe flag.

ParameterInfo.HasDefaultValue (new in .NET 4.5)

Gets a value indicating whether this parameter has a default value.

Aren't they the same? I quickly checked:

public void A(string value) { } public void B(string value, int i = -1) { } 

I wrote:

 var a = AInfo.GetParameters().Select(p => p.HasDefaultValue).ToArray(); var b = AInfo.GetParameters().Select(p => p.IsOptional).ToArray(); var c = BInfo.GetParameters().Select(p => p.HasDefaultValue).ToArray(); var d = BInfo.GetParameters().Select(p => p.IsOptional).ToArray(); //a equals b; and c equals d 

So in what context are they different? Why has BCL introduced HasDefaultValue in .NET 4.5 anew?

+8
reflection optional-parameters default-value
source share
3 answers

If we look at the implementation of IsOptional , we will see:

 public bool IsOptional { [__DynamicallyInvokable] get { return (this.Attributes & ParameterAttributes.Optional) != ParameterAttributes.None; } } 

It depends on the metadata flag, but as msdn says:

This method depends on the optional metadata flag. This flag can be inserted by compilers, but compilers are not required to do this.

This means that it depends on the compiler, and if we use another compiler, we can get the parameter whose default value will not have the IsOptional flag. Now let's see how the HasDefaultValue property is implemented:

 public override bool HasDefaultValue { get { if (this.m_noMetadata || this.m_noDefaultValue) return false; else return this.GetDefaultValueInternal(false) != DBNull.Value; } } 

It always checks if the parameter has a default value and is not dependent on the compiler. This may not be the 100% correct answer, just my thoughts.

UPDATE 0

Here's an example where the parameter has no default value, and IsOptional is true:

 public static void Method([Optional]string parameter) { } ParameterInfo parameterInfo = typeof(Program).GetMethod("Method").GetParameters()[0]; //Is true bool isOptional = parameterInfo.IsOptional; //Is false bool hasDefaultValue = parameterInfo.HasDefaultValue; 
+6
source share

Danny Chen and vvs0205 pinpoint the difference that IsOptional always depends on the compiler and checks if the parameter is an optional parameter, the default value of which is indicated by use HasDefaultValue .

 bool isOptional = parameterInfo.IsOptional; bool isOptionalWithADefaultValue = parameterInfo.HasDefaultValue; //.NET 4.5 bool isOptionalWithADefaultValue = (p.Attributes & ParameterAttributes.HasDefault) == ParameterAttributes.HasDefault; //.NET 4 and below 

Taken from here (catch some other undocumented methods to get the same in this thread)

+3
source share

You cannot get the output "they are the same" using "a is b" and c is d ", for example:

 int[] a = new[] { 0, 1, 5 }; var c = a.Where(n => n < 2).ToArray(); var d = a.Where(n => n < 3).ToArray(); //you can't say "2 == 3" even c equals to d in sequence 

Return to the topic, currently an optional parameter always has a default value, this conclusion is true "by now." But AFAIK is an undocumented behavior, which means that the compiler can change its behavior / implementation to optional parameters. Therefore, if you want to check (via reflection) if the parameter is optional, use the .IsOptional property. If you want to check if it has a default value (maybe it can be marked with some attribute, for example DefaultValue, maybe), use the .HasDefaultValue property. It sounds like extra words, but it's true.

+1
source share

All Articles