Částečné třídy a metody (Průvodce programováním v C#)
Definici třídy, struktury, rozhraní nebo metody je možné rozdělit na dva nebo více zdrojových souborů. Každý zdrojový soubor obsahuje oddíl definice typu nebo metody a všechny části jsou kombinovány při kompilaci aplikace.
Částečné třídy
Rozdělení definice třídy je žádoucí v několika situacích:
- Deklarování třídy nad samostatnými soubory umožňuje více programátorům pracovat na ní současně.
- Do třídy můžete přidat kód, aniž byste museli znovu vytvořit zdrojový soubor, který obsahuje automaticky vygenerovaný zdroj. Visual Studio tento přístup používá při vytváření model Windows Forms, kódu obálky webové služby atd. Můžete vytvořit kód, který tyto třídy používá, aniž byste museli upravovat soubor vytvořený sadou Visual Studio.
- Generátory zdrojů můžou generovat další funkce ve třídě.
K rozdělení definice třídy použijte modifikátor částečného klíčového slova. V praxi je každá částečná třída obvykle definována v samostatném souboru, což usnadňuje správu a rozšiřování třídy v průběhu času.
Následující Employee
příklad ukazuje, jak může být třída rozdělena mezi dva soubory: Employee_Part1.cs a Employee_Part2.cs.
// This is in Employee_Part1.cs
public partial class Employee
{
public void DoWork()
{
Console.WriteLine("Employee is working.");
}
}
// This is in Employee_Part2.cs
public partial class Employee
{
public void GoToLunch()
{
Console.WriteLine("Employee is at lunch.");
}
}
//Main program demonstrating the Employee class usage
public class Program
{
public static void Main()
{
Employee emp = new Employee();
emp.DoWork();
emp.GoToLunch();
}
}
// Expected Output:
// Employee is working.
// Employee is at lunch.
Klíčové partial
slovo označuje, že jiné části třídy, struktury nebo rozhraní mohou být definovány v oboru názvů. Všechny části musí používat partial
klíčové slovo. Všechny části musí být k dispozici v době kompilace, aby bylo možné vytvořit konečný typ. Všechny části musí mít stejnou přístupnost, například public
, private
atd.
Pokud je některá část deklarována jako abstraktní, považuje se celý typ za abstraktní. Pokud je některá část deklarována zapečetěná, považuje se celý typ zapečetěný. Pokud některá část deklaruje základní typ, celý typ dědí danou třídu.
Všechny části, které určují základní třídu, musí souhlasit, ale části, které vynechat základní třídu stále dědí základní typ. Části mohou určovat různá základní rozhraní a konečný typ implementuje všechna rozhraní uvedená všemi částečnými deklaracemi. Všechny třídy, struktury nebo členy rozhraní deklarované v částečné definici jsou k dispozici pro všechny ostatní části. Posledním typem je kombinace všech částí v době kompilace.
Poznámka:
partial
Modifikátor není k dispozici pro deklarace delegátu nebo výčtu.
Následující příklad ukazuje, že vnořené typy mohou být částečné, i když typ, který jsou vnořený uvnitř, není sám o sobě částečný.
class Container
{
partial class Nested
{
void Test() { }
}
partial class Nested
{
void Test2() { }
}
}
V době kompilace se sloučí atributy definic částečného typu. Představte si například následující deklarace:
[SerializableAttribute]
partial class Moon { }
[ObsoleteAttribute]
partial class Moon { }
Jsou ekvivalentní následujícím deklaracím:
[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }
Ze všech definic částečného typu se sloučí následující:
- Komentáře XML Pokud však obě deklarace částečného členu obsahují komentáře, budou zahrnuty pouze komentáře od implementovaného člena.
- rozhraní
- Atributy parametrů obecného typu
- class – atributy
- členové
Představte si například následující deklarace:
partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }
Jsou ekvivalentní následujícím deklaracím:
class Earth : Planet, IRotate, IRevolve { }
Omezení
Při práci s částečnými definicemi tříd je potřeba dodržovat několik pravidel:
- Všechny definice částečného typu, které mají být součástí stejného typu, musí být změněny pomocí
partial
. Například následující deklarace tříd generují chybu:public partial class A { } //public class A { } // Error, must also be marked partial
partial
Modifikátor může být zobrazen pouze bezprostředně před klíčovým slovemclass
,struct
nebointerface
.- Vnořené částečné typy jsou povoleny v definicích částečného typu, jak je znázorněno v následujícím příkladu:
partial class ClassWithNestedClass { partial class NestedClass { } } partial class ClassWithNestedClass { partial class NestedClass { } }
- Všechny definice částečného typu, které mají být součástí stejného typu, musí být definovány ve stejném sestavení a stejném modulu (.exe nebo .dll souboru). Částečné definice nemohou zahrnovat více modulů.
- Název třídy a parametry obecného typu se musí shodovat se všemi definicemi částečného typu. Obecné typy můžou být částečné. Každá částečná deklarace musí používat stejné názvy parametrů ve stejném pořadí.
- Následující klíčová slova v definici částečného typu jsou nepovinná, ale pokud jsou k dispozici u jedné definice částečného typu, musí být stejná jako u jiné částečné definice stejného typu:
Další informace naleznete v tématu Omezení parametrů typu.
Příklady
V následujícím příkladu jsou pole a konstruktor Coords
třídy deklarovány v jedné částečné definici třídy (Coords_Part1.cs
) a PrintCoords
metoda je deklarována v jiné částečné definici třídy (Coords_Part2.cs
). Toto oddělení ukazuje, jak lze částečné třídy rozdělit mezi více souborů, aby se usnadnila údržba.
// This is in Coords_Part1.cs
public partial class Coords
{
private int x;
private int y;
public Coords(int x, int y)
{
this.x = x;
this.y = y;
}
}
// This is in Coords_Part2.cs
public partial class Coords
{
public void PrintCoords()
{
Console.WriteLine("Coords: {0},{1}", x, y);
}
}
// Main program demonstrating the Coords class usage
class TestCoords
{
static void Main()
{
Coords myCoords = new Coords(10, 15);
myCoords.PrintCoords();
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
// Output: Coords: 10,15
Následující příklad ukazuje, že můžete také vyvíjet částečné struktury a rozhraní.
partial interface ITest
{
void Interface_Test();
}
partial interface ITest
{
void Interface_Test2();
}
partial struct S1
{
void Struct_Test() { }
}
partial struct S1
{
void Struct_Test2() { }
}
Částečné členy
Částečná třída nebo struktura může obsahovat částečný člen. Jedna část třídy obsahuje podpis člena. Implementace může být definována ve stejné nebo jiné části.
Implementace není nutná pro částečnou metodu, pokud podpis dodržuje následující pravidla:
- Deklarace neobsahuje žádné modifikátory přístupu. Metoda má
private
ve výchozím nastavení přístup. - Návratový typ je
void
. - Žádný z parametrů nemá
out
modifikátor. - Deklarace metody nemůže obsahovat žádný z následujících modifikátorů:
Metoda a všechna volání metody se odeberou v době kompilace, pokud neexistuje žádná implementace.
Každá metoda, která nevyhovuje všem těmto omezením, včetně vlastností a indexerů, musí poskytovat implementaci. Tato implementace může být dodána zdrojem generátoru. Částečné vlastnosti nelze implementovat pomocí automaticky implementovaných vlastností. Kompilátor nemůže rozlišovat mezi automaticky implementovanou vlastností a deklarací deklarace částečné vlastnosti.
Počínaje jazykem C# 13 může prováděcí deklarace částečné vlastnosti použít vlastnosti založené na polích k definování implementované deklarace. Vlastnost s podporou pole poskytuje stručnou syntaxi, kde field
klíčové slovo přistupuje k syntetizovanému záložnímu poli pro vlastnost. Můžete například napsat následující:
// in file1.cs
public partial class PropertyBag
{
// Defining declaration
public partial int MyProperty { get; set; }
}
// In file2.cs
public partial class PropertyBag
{
// Defining declaration
public partial int MyProperty { get => field; set; }
}
Můžete použít field
buď v objektu get
, set
nebo v obou.
Důležité
Klíčové field
slovo je funkce preview v jazyce C# 13. Pokud chcete použít field
kontextové klíčové slovo, musíte použít .NET 9 a nastavit prvek <LangVersion>
do preview
souboru projektu.
Měli byste být opatrní pomocí funkce klíčového field
slova ve třídě, která má pole s názvem field
. Nové field
klíčové slovo stínuje pole pojmenované field
v oboru přístupového objektu vlastnosti. Můžete změnit název field
proměnné nebo pomocí @
tokenu odkazovat na field
identifikátor jako @field
. Další informace najdete ve specifikaci funkce pro field
klíčové slovo.
Částečné metody umožňují implementaci jedné části třídy deklarovat člena. Implementátor jiné části třídy může tento člen definovat. Existují dva scénáře, kdy je toto oddělení užitečné: šablony, které generují často používaný kód, a generátory zdrojů.
- Kód šablony: Šablona si vyhrazuje název metody a podpis, aby vygenerovaný kód mohl metodu volat. Tyto metody se řídí omezeními, která vývojářům umožňují rozhodnout se, jestli metodu implementuje. Pokud metoda není implementována, kompilátor odebere podpis metody a všechna volání metody. Volání metody, včetně všech výsledků, které by nastaly z vyhodnocení argumentů ve voláních, nemají žádný účinek v době běhu. Proto jakýkoli kód v částečné třídě může volně používat částečnou metodu, i když implementace není zadána. Pokud je volána metoda, ale není implementována, nedojde k žádným chybám kompilace ani chyby za běhu.
- Generátory zdrojů: Zdrojové generátory poskytují implementaci členů. Vývojář člověka může přidat deklaraci členu (často s atributy přečtenými generátorem zdroje). Vývojář může napsat kód, který tyto členy volá. Zdrojový generátor běží během kompilace a poskytuje implementaci. V tomto scénáři se omezení částečných členů, které nemusí být implementované, často nedodržuje.
// Definition in file1.cs
partial void OnNameChanged();
// Implementation in file2.cs
partial void OnNameChanged()
{
// method body
}
- Částečné deklarace členů musí začínat kontextovým klíčovým slovem částečným.
- Částečné podpisy členů v obou částech částečného typu se musí shodovat.
- Částečný člen může mít statické a nebezpečné modifikátory.
- Částečný člen může být obecný. Omezení musí být stejná pro definici a implementaci deklarace metody. Názvy parametrů a typů nemusí být v implementující deklaraci stejné jako v definici.
- Delegáta můžete nastavit na částečnou definovanou a implementovanou metodu, ale ne na částečnou metodu, která nemá implementaci.
Specifikace jazyka C#
Další informace naleznete v části Částečné typy a Částečné metody ve specifikaci jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#. Nové funkce pro částečné metody jsou definovány ve specifikaci funkce.