-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clarify Optional Parameters and Nullable Optional Parameter Behavior in C#. #44408
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @shethaadit
The changes you've made emphasize the confusion rather than fixing it. A method signature can set the "default" value for an optional parameter. That's a different concept than the "default value" for a type. It also can be different than specifying a "missing" value. Consider this example:
public class Buffer<T>
{
private T[] _storage;
public Buffer(int size = 10)
{
_storage = new T[size];
}
}
The "default value" for size
is 10. That's different than the default value for the int
type (that's 0).
@@ -70,13 +70,14 @@ The following code implements the examples from this section along with some add | |||
|
|||
## Optional arguments | |||
|
|||
The definition of a method, constructor, indexer, or delegate can specify its parameters are required or optional. Any call must provide arguments for all required parameters, but can omit arguments for optional parameters. | |||
The definition of a method, constructor, indexer, or delegate can specify its parameters are required or optional. Any call must provide arguments for all required parameters, but can omit arguments for optional parameters. Additionally, nullable reference types (`T?`) implicitly have `null` as their default value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new sentence emphasizes the cause of the confusion, rather than removing it. We need to make a clear distinction between an optional parameter and the default value for a type.
@@ -99,7 +100,7 @@ IntelliSense uses brackets to indicate optional parameters, as shown in the foll | |||
![Screenshot showing IntelliSense quick info for the ExampleMethod method.](./media/named-and-optional-arguments/optional-examplemethod-parameters.png) | |||
|
|||
> [!NOTE] | |||
> You can also declare optional parameters by using the .NET <xref:System.Runtime.InteropServices.OptionalAttribute> class. `OptionalAttribute` parameters do not require a default value. However, if a default value is desired, take a look at <xref:System.Runtime.InteropServices.DefaultParameterValueAttribute> class. | |||
> You can also declare optional parameters by using the .NET <xref:System.Runtime.InteropServices.OptionalAttribute> class. `OptionalAttribute` parameters do not require a default value. However, if a default value is desired, take a look at <xref:System.Runtime.InteropServices.DefaultParameterValueAttribute> class. Additionally, nullable types (`T?`) implicitly default to `null` without needing to use these attributes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The additional sentence here mixes an optional parameter with the default value for a type.
|
||
Each optional parameter has a default value as part of its definition. If no argument is sent for that parameter, the default value is used. A default value must be one of the following types of expressions: | ||
|
||
- a constant expression; | ||
- an expression of the form `new ValType()`, where `ValType` is a value type, such as an [enum](../../language-reference/builtin-types/enum.md) or a [struct](../../language-reference/builtin-types/struct.md); | ||
- an expression of the form [default(ValType)](../../language-reference/operators/default.md), where `ValType` is a value type. | ||
- For nullable value types or nullable reference types (`T?`), the default value is always `null`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't correct. All of these declarations are legal. They conform to the first three bullet points:
public struct S
{
}
public class C {
void M(int? size = 5){} // a constant
void M(string? msg = "Hello World"){} // constant
void M(S someStruct = new S()){} // new expression, assuming `S` is a `struct`
void M(object? o = default) { } // OK default expression
void M(int size, S someStruct = default) {} // OK default expression addition parameter needed
void M(S? someStruct = default) {} // OK default expression
}
Hi @BillWagner, could you please check once if the updates makes sense? |
Summary
This PR improves the documentation for optional parameters in C# by:
T?
) parameters and optional parameters with default values.T? allTheOptionalMeanings = default
).Fixes #44404
Internal previews