A partial member has one declaring declaration and often one implementing declaration. The declaring declaration doesn't include a body. The implementing declaration provides the body of the member. Partial members enable class designers to provide member hooks that can be implemented by tooling such as source generators. Partial types and members provide a way for human developers to write part of a type while tools write other parts of the type. If the developer doesn't supply an optional implementing declaration, the compiler can remove the declaring declaration at compile time. The following conditions apply to partial members:
Declarations must begin with the contextual keyword partial.
Signatures in both parts of the partial type must match.
The partial keyword isn't allowed on constructors, finalizers, overloaded operators, or event declarations. Before C# 13, partial wasn't allowed on properties or indexers.
A partial method isn't required to have an implementing declaration in the following cases:
It doesn't have any accessibility modifiers (including the default private).
Any member that doesn't conform to all those restrictions (for example, public virtual partial void method), must provide an implementation. Partial properties and indexers must have an implementation.
The following example shows a partial method that conforms to the preceding restrictions:
C#
partialclassMyPartialClass
{
// Declaring definitionpartialvoidOnSomethingHappened(string s);
}
// This part can be in a separate file.partialclassMyPartialClass
{
// Comment out this method and the program// will still compile.partialvoidOnSomethingHappened(string s) =>
Console.WriteLine($"Something happened: {s}");
}
Partial members can also be useful in combination with source generators. For example a regex could be defined using the following pattern:
C#
publicpartialclassRegExSourceGenerator
{
[GeneratedRegex("cat|dog", RegexOptions.IgnoreCase, "en-US")]
privatestaticpartial Regex CatOrDogGeneratedRegex();
privatestaticvoidEvaluateText(string text)
{
if (CatOrDogGeneratedRegex().IsMatch(text))
{
// Take action with matching text
}
}
}
The preceding example shows a partial method that must have an implementing declaration. As part of a build, the Regular expression source generator creates the implementing declaration.
The following example shows a declaring declaration and an implementing declaration for a class. Because the method's return type isn't void (it's string) and its access is public, the method must have an implementing declaration:
C#
// Declaring declarationpublicpartialclassPartialExamples
{
///<summary>/// Gets or sets the number of elements that the List can contain.///</summary>publicpartialint Capacity { get; set; }
///<summary>/// Gets or sets the element at the specified index.///</summary>///<param name="index">The index</param>///<returns>The string stored at that index</returns>publicpartialstringthis[int index] { get; set; }
publicpartialstring? TryGetAt(int index);
}
publicpartialclassPartialExamples
{
private List<string> _items = [
"one",
"two",
"three",
"four",
"five"
];
// Implementing declaration///<summary>/// Gets or sets the number of elements that the List can contain.///</summary>///<remarks>/// If the value is less than the current capacity, the list will shrink to the/// new value. If the value is negative, the list isn't modified.///</remarks>publicpartialint Capacity
{
get => _items.Count;
set
{
if ((value != _items.Count) && (value >= 0))
{
_items.Capacity = value;
}
}
}
publicpartialstringthis[int index]
{
get => _items[index];
set => _items[index] = value;
}
///<summary>/// Gets the element at the specified index.///</summary>///<param name="index">The index</param>///<returns>The string stored at that index, or null if out of bounds</returns>publicpartialstring? TryGetAt(int index)
{
if (index < _items.Count)
{
return _items[index];
}
returnnull;
}
}
The preceding example illustrates rules on how the two declarations are combined:
Signature matches: In general, the signatures for the declaring and implementing declarations must match. This includes accessibility modifier on methods, properties, indexers, and individual accessors. It includes the parameter type and ref-kind modifiers on all parameters. The return type and any ref-kind modifier must match. Tuple member names must match. However, some rules are flexible:
The declaring and implementing declarations can have different nullable annotations settings. Meaning that one can be nullable oblivious and the other nullable enabled.
Nullability differences that don't involve oblivious nullability generates a warning.
Default parameter values don't need to match. The compiler issues a warning if the implementing declaration of a method or indexer declares a default parameter value.
The compiler issues a warning when parameter names don't match. The emitted IL contains the declaring declaration's parameter names.
Documentation comments: Documentation comments can be included from either declaration. If both the declaring and implementing declarations include documentation comments, the comments from the implementing declaration are included. In the preceding example, the documentation comments include:
For the Capacity property, the comments are taken from the implementing declaration. The implementing declaration comments are used when both declarations have /// comments.
For the indexer, the comments are taken from the declaring declaration. The implementing declaration doesn't include any /// comments.
For TryGetAt, the comments are taken from the implementing declaration. The declaring declaration doesn't include any /// comments.
The generated XML has documentation comments for all public members.
Most Attribute declarations are combined. However, all caller info attributes are defined with AllowMultiple=false. The compiler recognizes any caller info attribute on the declaring declaration. All caller info attributes on the implementing declaration are ignored. The compiler issues a warning if you add caller info attributes on the implementing declaration.
Μπορείτε να βρείτε την πηγή για αυτό το περιεχόμενο στο GitHub, όπου μπορείτε επίσης να δημιουργήσετε και να εξετάσετε ζητήματα και αιτήματα έλξης. Για περισσότερες πληροφορίες, ανατρέξτε στον οδηγό συνεργατών.
.NET σχόλια
.NET είναι ένα έργο ανοιχτού κώδικα. Επιλέξτε μια σύνδεση για να παρέχετε σχόλια:
Συμμετάσχετε στη σειρά meetup για να δημιουργήσετε κλιμακούμενες λύσεις AI που βασίζονται σε πραγματικές περιπτώσεις χρήσης με συναδέλφους προγραμματιστές και ειδικούς.