Partiella klasser och metoder (C#-programmeringsguide)

Det går att dela upp definitionen av en klass, en struct, ett gränssnitt eller en metod över två eller flera källfiler. Varje källfil innehåller ett avsnitt av typen eller metoddefinitionen, och alla delar kombineras när programmet kompileras.

Partiella klasser

Det finns flera situationer när det är önskvärt att dela upp en klassdefinition:

  • Om du deklarerar en klass över separata filer kan flera programmerare arbeta med den samtidigt.
  • Du kan lägga till kod i klassen utan att behöva återskapa källfilen som innehåller automatiskt genererad källa. Visual Studio använder den här metoden när den skapar Windows Forms, webbtjänstomslutningskod och så vidare. Du kan skapa kod som använder dessa klasser utan att behöva ändra filen som skapats av Visual Studio.
  • Källgeneratorer kan generera extra funktioner i en klass.

Om du vill dela upp en klassdefinition använder du den partiella nyckelordsmodifieraren, som du ser här:

public partial class Employee
{
    public void DoWork()
    {
    }
}

public partial class Employee
{
    public void GoToLunch()
    {
    }
}

Nyckelordet partial anger att andra delar av klassen, struct eller gränssnittet kan definieras i namnområdet. Alla delar måste använda nyckelordet partial . Alla delar måste vara tillgängliga vid kompileringstillfället för att bilda den slutliga typen. Alla delar måste ha samma hjälpmedel, till exempel public, privateoch så vidare.

Om någon del förklaras abstrakt anses hela typen vara abstrakt. Om någon del förklaras förseglad anses hela typen vara förseglad. Om någon del deklarerar en bastyp ärver hela typen den klassen.

Alla delar som anger en basklass måste överensstämma, men delar som utelämnar en basklass ärver fortfarande bastypen. Delar kan ange olika basgränssnitt och den slutliga typen implementerar alla gränssnitt som anges av alla partiella deklarationer. Alla klass-, struct- eller gränssnittsmedlemmar som deklareras i en partiell definition är tillgängliga för alla andra delar. Den sista typen är kombinationen av alla delar vid kompileringstiden.

Kommentar

Modifieraren partial är inte tillgänglig för ombuds- eller uppräkningsdeklarationer.

I följande exempel visas att kapslade typer kan vara partiella, även om typen de är kapslade i inte är delvis.

class Container
{
    partial class Nested
    {
        void Test() { }
    }

    partial class Nested
    {
        void Test2() { }
    }
}

Vid kompileringstillfället sammanfogas attribut för definitioner av partiell typ. Tänk till exempel på följande deklarationer:

[SerializableAttribute]
partial class Moon { }

[ObsoleteAttribute]
partial class Moon { }

De motsvarar följande deklarationer:

[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }

Följande sammanfogas från alla definitioner av partiell typ:

  • XML-kommentarer
  • Gränssnitt
  • parameterattribut av generisk typ
  • klassattribut
  • medlemmar

Tänk till exempel på följande deklarationer:

partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }

De motsvarar följande deklarationer:

class Earth : Planet, IRotate, IRevolve { }

Begränsningar

Det finns flera regler att följa när du arbetar med partiella klassdefinitioner:

  • Alla definitioner av partiell typ som är avsedda att vara delar av samma typ måste ändras med partial. Följande klassdeklarationer genererar till exempel ett fel:
    public partial class A { }
    //public class A { }  // Error, must also be marked partial
    
  • Modifieraren partial kan bara visas omedelbart före nyckelordet class, structeller interface.
  • Kapslade partiella typer tillåts i definitioner av partiell typ enligt följande exempel:
    partial class ClassWithNestedClass
    {
        partial class NestedClass { }
    }
    
    partial class ClassWithNestedClass
    {
        partial class NestedClass { }
    }
    
  • Alla definitioner av partiell typ som är avsedda att vara delar av samma typ måste definieras i samma sammansättning och samma modul (.exe eller .dll fil). Partiella definitioner kan inte sträcka sig över flera moduler.
  • Klassnamnet och parametrarna för generisk typ måste matcha alla definitioner av partiell typ. Generiska typer kan vara partiella. Varje partiell deklaration måste använda samma parameternamn i samma ordning.
  • Följande nyckelord i en definition av partiell typ är valfria, men om de finns i en definition av partiell typ kan det inte vara i konflikt med nyckelorden som anges i en annan partiell definition för samma typ:

Mer information finns i Begränsningar för typparametrar.

Exempel

I följande exempel deklareras fälten och konstruktorn för klassen , Coordsi en partiell klassdefinition, och medlemmen, PrintCoords, deklareras i en annan partiell klassdefinition.

public partial class Coords
{
    private int x;
    private int y;

    public Coords(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

public partial class Coords
{
    public void PrintCoords()
    {
        Console.WriteLine("Coords: {0},{1}", x, y);
    }
}

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

I följande exempel visas att du också kan utveckla partiella structs och gränssnitt.

partial interface ITest
{
    void Interface_Test();
}

partial interface ITest
{
    void Interface_Test2();
}

partial struct S1
{
    void Struct_Test() { }
}

partial struct S1
{
    void Struct_Test2() { }
}

Partiella metoder

En partiell klass eller struct kan innehålla en partiell metod. En del av klassen innehåller metodens signatur. En implementering kan definieras i samma del eller i en annan del.

En implementering krävs inte för en partiell metod när signaturen följer följande regler:

  • Deklarationen innehåller inga åtkomstmodifierare. Metoden har private åtkomst som standard.
  • Returtypen är void.
  • Ingen av parametrarna har out modifieraren.
  • Metoddeklarationen kan inte innehålla någon av följande modifierare:

Metoden och alla anrop till metoden tas bort vid kompileringstillfället när det inte finns någon implementering.

Alla metoder som inte överensstämmer med alla dessa begränsningar (till exempel public virtual partial void metod) måste tillhandahålla en implementering. Implementeringen kan tillhandahållas av en källgenerator.

Med partiella metoder kan implementeraren av en del av en klass deklarera en metod. Implementeraren för en annan del av klassen kan definiera den metoden. Det finns två scenarier där den här separationen är användbar: mallar som genererar pannplåtskod och källgeneratorer.

  • Mallkod: Mallen reserverar ett metodnamn och en signatur så att genererad kod kan anropa metoden. Dessa metoder följer de begränsningar som gör det möjligt för en utvecklare att bestämma om metoden ska implementeras. Om metoden inte implementeras tar kompilatorn bort metodsignaturen och alla anrop till metoden. Anropen till metoden, inklusive resultat som skulle uppstå vid utvärdering av argument i anropen, har ingen effekt vid körning. Därför kan all kod i den partiella klassen fritt använda en partiell metod, även om implementeringen inte tillhandahålls. Inga kompilerings- eller körningsfel resulterar om metoden anropas men inte implementeras.
  • Källgeneratorer: Källgeneratorer tillhandahåller en implementering av metoder. Den mänskliga utvecklaren kan lägga till metoddeklarationen (ofta med attribut som läse av källgeneratorn). Utvecklaren kan skriva kod som anropar dessa metoder. Källgeneratorn körs under kompileringen och tillhandahåller implementeringen. I det här scenariot följs inte ofta begränsningarna för partiella metoder som kanske inte implementeras.
// Definition in file1.cs
partial void OnNameChanged();

// Implementation in file2.cs
partial void OnNameChanged()
{
  // method body
}
  • Partiella metoddeklarationer måste börja med det partiella kontextuella nyckelordet.
  • Signaturer för partiella metoder i båda delarna av den partiella typen måste matcha.
  • Partiella metoder kan ha statiska och osäkra modifierare.
  • Partiella metoder kan vara generiska. Begränsningar måste vara desamma för att definiera och implementera metoddeklarationen. Parameter- och typparameternamn behöver inte vara samma i implementeringsdeklarationen som i den definierande.
  • Du kan göra ett ombud till en partiell metod som definierats och implementerats, men inte till en partiell metod som inte har någon implementering.

Språkspecifikation för C#

Mer information finns i Partiella typer och Partiella metoder i C#-språkspecifikationen. Språkspecifikationen är den slutgiltiga källan för C#-syntax och -användning. De ytterligare funktionerna för partiella metoder definieras i funktionsspecifikationen.

Se även