Partiell medlem (C#-referens)
En partiell medlem har en deklarerande förklaring och ofta en genomförandedeklaration. Deklareringsdeklarationen innehåller inte någon brödtext. Genomförandedeklarationen innehåller medlemmens brödtext. Partiella medlemmar gör det möjligt för klassdesigners att tillhandahålla medlemskrokar som kan implementeras med verktyg som källgeneratorer. Partiella typer och medlemmar är ett sätt för mänskliga utvecklare att skriva en del av en typ medan verktyg skriver andra delar av typen. Om utvecklaren inte anger någon valfri implementeringsdeklaration kan kompilatorn ta bort deklareringsdeklarationen vid kompileringstillfället. Följande villkor gäller för partiella medlemmar:
- Deklarationer måste börja med det kontextuella nyckelordet partiellt.
- Signaturer i båda delarna av den partiella typen måste matcha.
Nyckelordet partial
tillåts inte på konstruktorer, finalatorer, överbelastade operatorer eller händelsedeklarationer. Före C# 13 partial
tilläts inte för egenskaper eller indexerare.
En partiell metod krävs inte för att ha en implementeringsdeklaration i följande fall:
- Den har inga hjälpmedelsmodifierare (inklusive standardinställningen
private
). - Den returnerar
void
. - Den har inga
out
parametrar. - Den har inte någon av följande modifierare
virtual
, ,override
sealed
, ,new
ellerextern
.
Alla medlemmar som inte följer alla dessa begränsningar (till exempel public virtual partial void
metod) måste tillhandahålla en implementering. Partiella egenskaper och indexerare måste ha en implementering.
I följande exempel visas en partiell metod som överensstämmer med de föregående begränsningarna:
partial class MyPartialClass
{
// Declaring definition
partial void OnSomethingHappened(string s);
}
// This part can be in a separate file.
partial class MyPartialClass
{
// Comment out this method and the program
// will still compile.
partial void OnSomethingHappened(string s) =>
Console.WriteLine($"Something happened: {s}");
}
Partiella medlemmar kan också vara användbara i kombination med källgeneratorer. Till exempel kan en regex definieras med hjälp av följande mönster:
public partial class RegExSourceGenerator
{
[GeneratedRegex("cat|dog", RegexOptions.IgnoreCase, "en-US")]
private static partial Regex CatOrDogGeneratedRegex();
private static void EvaluateText(string text)
{
if (CatOrDogGeneratedRegex().IsMatch(text))
{
// Take action with matching text
}
}
}
Föregående exempel visar en partiell metod som måste ha en implementeringsdeklaration. Som en del av en version skapar källgeneratorn för reguljära uttryck implementeringsdeklarationen.
I följande exempel visas en deklareringsdeklaration och en implementeringsdeklaration för en klass. Eftersom metodens returtyp inte void
är (den är ) och dess åtkomst är public
måste metoden ha en implementeringsdeklarationstring
:
// Declaring declaration
public partial class PartialExamples
{
/// <summary>
/// Gets or sets the number of elements that the List can contain.
/// </summary>
public partial int 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>
public partial string this[int index] { get; set; }
public partial string? TryGetAt(int index);
}
public partial class PartialExamples
{
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>
public partial int Capacity
{
get => _items.Count;
set
{
if ((value != _items.Count) && (value >= 0))
{
_items.Capacity = value;
}
}
}
public partial string this[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>
public partial string? TryGetAt(int index)
{
if (index < _items.Count)
{
return _items[index];
}
return null;
}
}
Föregående exempel illustrerar regler för hur de två deklarationerna kombineras:
- Signaturmatchningar: I allmänhet måste signaturerna för deklarerings- och implementeringsdeklarationerna matcha. Detta omfattar hjälpmedelsmodifierare för metoder, egenskaper, indexerare och enskilda åtkomstorer. Den innehåller parametertypen och ref-kind-modifierare för alla parametrar. Returtypen och alla ref-kind-modifierare måste matcha. Tuppelns medlemsnamn måste matcha. Vissa regler är dock flexibla:
- Deklarerings- och implementeringsdeklarationerna kan ha olika inställningar för null-anteckningar . Vilket innebär att den ena kan vara nullbar omedveten och den andra nullbar aktiverad.
- Nullabilitetsskillnader som inte omfattar omedveten nullabilitet genererar en varning.
- Standardparametervärden behöver inte matcha. Kompilatorn utfärdar en varning om implementeringsdeklarationen för en metod eller indexerare deklarerar ett standardparametervärde.
- Kompilatorn utfärdar en varning när parameternamnen inte matchar. Den utgivna IL:n innehåller deklareringsdeklarationens parameternamn.
- Dokumentationskommentar: Dokumentationskommentar kan tas med från deklarationen. Om både deklarerings- och implementeringsdeklarationerna innehåller dokumentationskommenter inkluderas kommentarerna från implementeringsdeklarationen. I föregående exempel innehåller dokumentationskommentarna:
- För egenskapen
Capacity
hämtas kommentarerna från implementeringsdeklarationen. Implementeringsdeklarationskommentarna används när båda deklarationerna har///
kommentarer. - För indexeraren tas kommentarerna från deklareringsdeklarationen. Implementeringsdeklarationen innehåller inga
///
kommentarer. - För
TryGetAt
tas kommentarerna från genomförandedeklarationen. Deklareringsdeklarationen innehåller inga///
kommentarer. - Den genererade XML-koden har dokumentationskommentar för alla
public
medlemmar.
- För egenskapen
- De flesta attributdeklarationer kombineras . Alla informationsattribut för anropare definieras dock med
AllowMultiple=false
. Kompilatorn identifierar alla anroparinformationsattribut i deklareringsdeklarationen. Alla anroparinformationsattribut i implementeringsdeklarationen ignoreras. Kompilatorn utfärdar en varning om du lägger till anroparinformationsattribut i implementeringsdeklarationen.