2023-06-16 15:47:49 +02:00

81 lines
3.3 KiB
Plaintext

== Why is this an issue?
https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.defaultvalueattribute[DefaultValue] does not make the compiler set the default value, as its name may suggest. What you probably wanted to use is https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.defaultparametervalueattribute[DefaultParameterValue].
The https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.defaultvalueattribute[DefaultValue] attribute from the `System.ComponentModel` namespace, is sometimes used to declare a member's default value. This can be used, for instance, by the reset feature of a visual designer or by a code generator.
[source,csharp]
----
public void DoStuff([DefaultValue(4)] int i)
{
// i is not automatically assigned 4
}
----
The https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.optionalattribute[Optional] attribute from the `System.Runtime.InteropServices` namespace is sometimes used to indicate that a parameter is optional, as an alternative to the language-specific construct.
[source,csharp]
----
public void DoStuff([Optional] int i)
{
// i would be assigned default(int) = 0
}
----
The use of `[DefaultValue]` with `[Optional]` has no more effect than `[Optional]` alone. That's because `[DefaultValue]` doesn't actually do anything; it merely indicates the intent for the value.
[source,csharp,diff-id=1,diff-type=noncompliant]
----
class MyClass
{
public void DoStuff([Optional][DefaultValue(4)] int i, int j = 5) // Noncompliant
{
Console.WriteLine(i);
}
public static void Main()
{
new MyClass().DoStuff(); // prints 0, since [DefaultValue] doesn't actually set the default, and default(int) is used instead
}
}
----
More than likely, `[DefaultValue]` was used in confusion instead of `[DefaultParameterValue]`, the language-agnostic version of the default parameter initialization mechanism provided by C#.
[source,csharp,diff-id=1,diff-type=compliant]
----
class MyClass
{
public void DoStuff([Optional][DefaultParameterValue(4)] int i, int j = 5)
{
Console.WriteLine(i);
}
public static void Main()
{
new MyClass().DoStuff(); // prints 4
}
}
----
Notice that you can't use both `[DefaultParameterValue]` and default parameter initialization on the same parameter.
[source,csharp]
----
void DoStuff([Optional][DefaultParameterValue(4)] int i = 5) // Error CS1745 Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute
----
== Resources
=== Documentation
* https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.optionalattribute[OptionalAttribute Class]
* https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.defaultvalueattribute[DefaultValueAttribute Class]
* https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.defaultparametervalueattribute[DefaultParameterValueAttribute Class]
* https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#optional-arguments[Optional arguments (C# Programming Guide)]
=== Articles & blog posts
* https://stackoverflow.com/questions/40171095/use-optional-defaultparametervalue-attribute-or-not[Stack Overflow - Use "Optional, DefaultParameterValue" attribute, or not?]
include::../rspecator.adoc[]