interface (C#-referens)
Ett gränssnitt definierar ett kontrakt. Alla class
, record
eller struct
som implementerar det kontraktet måste tillhandahålla en implementering av de medlemmar som definierats i gränssnittet. Ett gränssnitt kan definiera en standardimplementering för medlemmar. Det kan också definiera static
medlemmar för att tillhandahålla en enda implementering för vanliga funktioner. Från och med C# 11 kan ett gränssnitt definiera static abstract
eller static virtual
medlemmar för att deklarera att en implementeringstyp måste ange de deklarerade medlemmarna. Vanligtvis static virtual
deklarerar metoder att en implementering måste definiera en uppsättning överlagrade operatorer.
I följande exempel måste klassen ImplementationClass
implementera en metod med namnet SampleMethod
som inte har några parametrar och returnerar void
.
Mer information och exempel finns i Gränssnitt.
Ett gränssnitt på den översta nivån, ett som deklareras i ett namnområde men inte är kapslat i en annan typ, kan deklareras public
eller internal
. Standardvärdet är internal
. Kapslade gränssnittsdeklarationer, som deklareras i en annan typ, kan deklareras med hjälp av alla åtkomstmodifierare.
Gränssnittsmedlemmar utan implementering kan inte inkludera en åtkomstmodifierare. Medlemmar med en standardimplementering kan inkludera alla åtkomstmodifierare.
Exempelgränssnitt
interface ISampleInterface
{
void SampleMethod();
}
class ImplementationClass : ISampleInterface
{
// Explicit interface member implementation:
void ISampleInterface.SampleMethod()
{
// Method implementation.
}
static void Main()
{
// Declare an interface instance.
ISampleInterface obj = new ImplementationClass();
// Call the member.
obj.SampleMethod();
}
}
Ett gränssnitt kan vara medlem i ett namnområde eller en klass. En gränssnittsdeklaration kan innehålla deklarationer (signaturer utan implementering) av följande medlemmar:
Standardgränssnittsmedlemmar
Dessa föregående medlemsdeklarationer innehåller vanligtvis inte någon brödtext. En gränssnittsmedlem kan deklarera en brödtext. Medlemsorgan i ett gränssnitt är standardimplementeringen. Medlemmar med organ tillåter gränssnittet att tillhandahålla en "standardimplementering" för klasser och structs som inte tillhandahåller en övergripande implementering.
Viktigt!
Att lägga till standardgränssnittsmedlemmar tvingar alla ref struct
som implementerar gränssnittet att lägga till en explicit deklaration av medlemmen.
Ett gränssnitt kan innehålla:
- Konstanter
- Operatorer
- Statisk konstruktor.
- Kapslade typer
- Statiska fält, metoder, egenskaper, indexerare och händelser
- Medlemsdeklarationer med den explicita syntaxen för gränssnittsimplementering.
- Explicita åtkomstmodifierare (standardåtkomsten är
public
).
Statiska abstrakta och virtuella medlemmar
Från och med C# 11 kan ett gränssnitt deklarera static abstract
och static virtual
medlemmar för alla medlemstyper utom fält. Gränssnitt kan deklarera att implementeringstyper måste definiera operatorer eller andra statiska medlemmar. Med den här funktionen kan allmänna algoritmer ange talliknande beteende. Du kan se exempel i de numeriska typerna i .NET-körningen, till exempel System.Numerics.INumber<TSelf>. Dessa gränssnitt definierar vanliga matematiska operatorer som implementeras av många numeriska typer. Kompilatorn måste matcha anrop till static virtual
och static abstract
metoder vid kompileringstillfället. Metoderna static virtual
och static abstract
som deklareras i gränssnitten har inte någon runtime dispatch-mekanism som motsvarar virtual
eller abstract
metoder som deklarerats i klasser. Kompilatorn använder i stället typinformation som är tillgänglig vid kompileringstillfället. Därför static virtual
deklareras metoder nästan uteslutande i generiska gränssnitt. Dessutom deklarerar de flesta gränssnitt som deklarerar static virtual
eller static abstract
metoder att en av typparametrarna måste implementera det deklarerade gränssnittet. Till exempel INumber<T>
deklarerar gränssnittet som T
måste implementera INumber<T>
. Kompilatorn använder typargumentet för att lösa anrop till de metoder och operatorer som deklareras i gränssnittsdeklarationen. Typen implementerar INumber<int>
till exempel int
. När typparametern T
anger typargumentet int
anropas de medlemmar som static
deklareras på int
. Alternativt anropas de static
medlemmar som deklarerats för typen när double
är typargumentetdouble
.
Viktigt!
Metodsändning för och static virtual
metoder som deklarerats i gränssnitt löses med hjälp av kompileringstidstypen för static abstract
ett uttryck. Om körningstypen för ett uttryck härleds från en annan kompileringstidstyp anropas de statiska metoderna på bastypen (kompileringstid).
Du kan prova den här funktionen genom att arbeta med självstudien om statiska abstrakta medlemmar i gränssnitt.
Gränssnittsarv
Gränssnitt får inte innehålla instanstillstånd. Statiska fält tillåts nu, men instansfält tillåts inte i gränssnitt. Autoegenskaper för instanser stöds inte i gränssnitt, eftersom de implicit deklarerar ett dolt fält. Den här regeln har en subtil effekt på egenskapsdeklarationer. I en gränssnittsdeklaration deklarerar inte följande kod en automatiskt implementerad egenskap som den gör i en class
eller struct
. I stället deklareras en egenskap som inte har någon standardimplementering, men som måste implementeras i alla typer som implementerar gränssnittet:
public interface INamed
{
public string Name {get; set;}
}
Ett gränssnitt kan ärva från ett eller flera basgränssnitt. När ett gränssnitt ärver från ett annat gränssnitt måste en typ som implementerar det härledda gränssnittet implementera alla medlemmar i basgränssnitten samt de som deklareras i det härledda gränssnittet, enligt följande kod:
public interface I1
{
void M1();
}
public interface I2 : I1
{
void M2();
}
public class C : I2
{
// implements I1.M1
public void M1() { }
// implements I2.M2
public void M2() { }
}
När ett gränssnitt åsidosätter en metod som implementerats i ett basgränssnitt måste det använda den explicita syntaxen för gränssnittsimplementering .
När en bastyplista innehåller en basklass och gränssnitt måste basklassen komma först i listan.
En klass som implementerar ett gränssnitt kan uttryckligen implementera medlemmar i gränssnittet. En explicit implementerad medlem kan inte nås via en klassinstans, utan bara via en instans av gränssnittet. Dessutom kan standardgränssnittsmedlemmar endast nås via en instans av gränssnittet.
Mer information om explicit gränssnittsimplementering finns i Explicit gränssnittsimplementering.
Exempel på gränssnittsimplementering
I följande exempel visas gränssnittsimplementering. I det här exemplet innehåller gränssnittet egenskapsdeklarationen och klassen innehåller implementeringen. Alla instanser av en klass som implementerar har heltalsegenskaper IPoint
x
och y
.
interface IPoint
{
// Property signatures:
int X { get; set; }
int Y { get; set; }
double Distance { get; }
}
class Point : IPoint
{
// Constructor:
public Point(int x, int y)
{
X = x;
Y = y;
}
// Property implementation:
public int X { get; set; }
public int Y { get; set; }
// Property implementation
public double Distance =>
Math.Sqrt(X * X + Y * Y);
}
class MainClass
{
static void PrintPoint(IPoint p)
{
Console.WriteLine("x={0}, y={1}", p.X, p.Y);
}
static void Main()
{
IPoint p = new Point(2, 3);
Console.Write("My Point: ");
PrintPoint(p);
}
}
// Output: My Point: x=2, y=3
Språkspecifikation för C#
Mer information finns i avsnittet Gränssnitt i C#-språkspecifikationen, funktionsspecifikationen för C# 8 – Standardgränssnittsmedlemmar och funktionsspecifikationen för C# 11 – statiska abstrakta medlemmar i gränssnitt