interface (C# referencia)
Az interfész egy szerződést határoz meg. Bármely class
, record
vagy struct
a szerződést megvalósítónak biztosítania kell a felületen meghatározott tagok megvalósítását. Egy felület meghatározhat egy alapértelmezett implementációt a tagok számára. Tagokat is meghatározhat static
annak érdekében, hogy egységes implementációt biztosítson a közös funkciókhoz. A C# 11-től kezdődően a felület definiálhatja static abstract
vagy static virtual
a tagok deklarálhatják, hogy egy implementálási típusnak meg kell adnia a deklarált tagokat. A metódusok általában azt deklarálják, static virtual
hogy egy implementációnak túlterhelt operátorokat kell meghatároznia.
Az alábbi példában az osztálynak ImplementationClass
olyan metódust SampleMethod
kell implementálnia, amely nem tartalmaz paramétereket, és visszaadja azokat void
.
További információkért és példákért lásd : Interfészek.
A névtérben deklarált, de egy másik típusba nem beágyazott legfelső szintű felület deklarálható vagy internal
deklarálhatópublic
. Az alapértelmezett érték internal
. A beágyazott felületi deklarációk, amelyek más típuson belül deklarálva vannak, bármilyen hozzáférési módosító használatával deklarálhatók.
A megvalósítás nélküli felülettagok nem tartalmazhatnak hozzáférési módosító elemet. Az alapértelmezett implementációval rendelkező tagok bármilyen hozzáférés-módosítót tartalmazhatnak.
Példa felület
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();
}
}
Egy felület tagja lehet egy névtérnek vagy egy osztálynak. A felületi deklarációk a következő tagok nyilatkozatait (implementálás nélküli aláírásokat) tartalmazhatnak:
Alapértelmezett illesztőtagok
Ezek a korábbi tagdeklarációk általában nem tartalmaznak törzset. A felület tagja deklarálhat egy törzset. Az interfész tagszervezetei az alapértelmezett implementációk. A testületekkel rendelkező tagok lehetővé teszik, hogy az interfész "alapértelmezett" implementációt biztosítson az olyan osztályok és szerkezetek számára, amelyek nem biztosítanak felülíró megvalósítást.
Fontos
Az alapértelmezett illesztőtagok hozzáadása kényszeríti az illesztőt megvalósító összes ref struct
felhasználót, hogy explicit deklarációt adjon hozzá a taghoz.
A felület a következőket tartalmazhatja:
- Állandók
- Operátorok
- Statikus konstruktor.
- Beágyazott típusok
- Statikus mezők, metódusok, tulajdonságok, indexelők és események
- Tagdeklarációk az explicit felület implementálási szintaxisával.
- Explicit hozzáférés-módosítók (az alapértelmezett hozzáférés).
public
Statikus absztrakt és virtuális tagok
A C# 11-től kezdődően egy felület a mezők kivételével minden tagtípushoz deklarálhat static abstract
és static virtual
tagokat. Az interfészek deklarálhatják, hogy a implementálási típusoknak operátorokat vagy más statikus tagokat kell meghatározniuk. Ez a funkció lehetővé teszi, hogy az általános algoritmusok számszerű viselkedést adjanak meg. A .NET-futtatókörnyezetben a numerikus típusok példái láthatók, például System.Numerics.INumber<TSelf>. Ezek az interfészek olyan gyakori matematikai operátorokat határoznak meg, amelyeket számos numerikus típus implementál. A fordítónak fordításkor meg kell oldania a static virtual
hívásokat és static abstract
a metódusokat. Az static virtual
illesztőkben deklarált metódusok és static abstract
metódusok nem rendelkeznek az osztályokban deklarált vagy abstract
azokhoz hasonló futtatókörnyezeti küldési virtual
mechanizmussal. Ehelyett a fordító a fordításkor elérhető típusinformációkat használja. Ezért a static virtual
módszerek szinte kizárólag általános felületeken vannak deklarálva. Ezenkívül a legtöbb deklarált interfésznek vagy static abstract
metódusnak azt kell deklarálniastatic virtual
, hogy az egyik típusparaméternek implementálnia kell a deklarált interfészt. Az interfész például azt deklarálja, INumber<T>
hogy T
implementálnia INumber<T>
kell. A fordító a típusargumentum használatával oldja fel a felületi deklarációban deklarált metódusok és operátorok hívásait. A típus például implementálja a int
következőt INumber<int>
: . Amikor a típusparaméter T
a típusargumentumot int
jelöli, a rendszer meghívja a static
deklarált int
tagokat. Másik lehetőségként, ha double
a típus argumentumot adja meg, a rendszer meghívja a static
double
típuson deklarált tagokat.
Fontos
A metódusküldés static abstract
és static virtual
a felületeken deklarált metódusok feloldása egy kifejezés fordítási időtípusával történik. Ha egy kifejezés futásidejű típusa egy másik fordítási időtípusból származik, a rendszer meghívja az alap (fordítási idő) típus statikus metódusait.
Ezt a funkciót úgy is kipróbálhatja, ha a felületi statikus absztrakt tagokról szóló oktatóanyagot használja.
Interfész öröklése
Előfordulhat, hogy az interfészek nem tartalmaznak példányállapotot. Bár a statikus mezők most már engedélyezettek, a példánymezők nem engedélyezettek a felületeken. A példány automatikus tulajdonságai nem támogatottak az interfészekben, mivel implicit módon deklarálnának egy rejtett mezőt. Ez a szabály enyhe hatással van a tulajdonságdeklarációkra. A felületi deklarációkban a következő kód nem deklarál automatikusan implementált tulajdonságot, ahogyan az egy class
vagy struct
. Ehelyett egy olyan tulajdonságot deklarál, amely nem rendelkezik alapértelmezett implementációval, de az interfészt megvalósító bármilyen típusban implementálni kell:
public interface INamed
{
public string Name {get; set;}
}
Egy interfész egy vagy több alapillesztőtől örökölhet. Ha egy interfész öröklődik egy másik interfésztől, a származtatott interfészt implementáló típusnak az alapillesztőkben lévő összes tagot, valamint a származtatott felületen deklarált tagokat kell implementálnia, ahogyan az az alábbi kódban is látható:
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() { }
}
Ha egy felület felülír egy alapillesztőben implementált metódust, az explicit felület implementálási szintaxisát kell használnia.
Ha egy alaptípuslista alaposztályt és interfészeket tartalmaz, az alaposztálynak a listában kell elsőnek lennie.
Az interfészt megvalósító osztály explicit módon implementálhatja az adott felület tagjait. Egy explicit módon implementált tag nem érhető el osztálypéldányon keresztül, csak a felület egy példányán keresztül. Emellett az alapértelmezett illesztőtagok csak a felület egy példányán keresztül érhetők el.
További információ az explicit felület implementálásáról: Explicit Interface Implementáció.
Példa felület implementálására
Az alábbi példa a felület implementálását mutatja be. Ebben a példában a felület tartalmazza a tulajdonságdeklarációt, az osztály pedig a megvalósítást. A megvalósító IPoint
osztály minden példánya egész számtulajdonságokkal x
és 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
C# nyelvspecifikáció
További információkért tekintse meg a C# nyelvi specifikáció Felületek szakaszát, a C# 8 – Alapértelmezett felülettagok funkcióspecifikációját, valamint a C# 11 – statikus absztrakt tagok funkciós specifikációját az interfészekben