interface (Informations de référence sur C#)
Une interface définit un contrat. Tout class
, record
ou struct
qui implémente ce contrat doit fournir une implémentation des membres définis dans l’interface. Une interface peut définir une implémentation par défaut pour les membres. Elle peut également définir des membres static
afin de fournir une implémentation unique pour les fonctionnalités courantes. À partir de C# 11, une interface peut définir des membres static abstract
ou static virtual
pour déclarer qu’un type d’implémentation doit fournir les membres déclarés. En règle générale, les méthodes static virtual
déclarent qu’une implémentation doit définir un ensemble d’opérateurs surchargés.
Dans l’exemple suivant, la classe ImplementationClass
doit implémenter une méthode nommée SampleMethod
qui n’a aucun paramètre et qui retourne void
.
Pour plus d’informations et d’exemples, consultez Interfaces.
Une interface de haut niveau, déclarée dans un espace de noms sans être imbriquée dans un autre type, peut être déclarée public
ou internal
. Par défaut, il s’agit de internal
. Des déclarations d’interfaces imbriquées, celles déclarées dans un autre type, peuvent être déclarées en utilisant tout modificateur d’accès.
Les membres d’interfaces sans implémentation ne peuvent pas inclure de modificateur d’accès. Les membres avec une implémentation par défaut peuvent inclure un modificateur d’accès.
Exemple d’interface
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();
}
}
Une interface peut être membre d’un espace de noms ou d’une classe. Une déclaration d’interface peut contenir des déclarations (signatures sans implémentation) des membres suivants :
Membres d’interface par défaut
Ces déclarations de membre précédentes ne contiennent généralement pas de corps. Un membre d’interface peut déclarer un corps. Les corps membres d’une interface sont l’implémentation par défaut. Les membres dotés de corps permettent à l’interface de fournir une implémentation « par défaut » pour les classes et les structs qui ne fournissent pas d’implémentation de remplacement.
Important
L’ajout de membres d’interfaces par défaut applique les ref struct
qui implémentent l’interface pour ajouter une déclaration explicite de ce membre.
Une interface peut inclure :
- Constantes
- Opérateurs
- Constructeur statique.
- Types imbriqués
- Champs statiques, méthodes, propriétés, indexeurs et événements
- Déclarations de membre utilisant la syntaxe d’implémentation d’interface explicite.
- Modificateurs d’accès explicites (l’accès par défaut est
public
).
Membres virtuels et abstraits statiques
À partir de C# 11, une interface peut déclarer des membres static abstract
et static virtual
pour tous les types de membres, à l’exception des champs. Les interfaces peuvent déclarer que les types d’implémentation doivent définir des opérateurs ou d’autres membres statiques. Cette fonctionnalité permet aux algorithmes génériques de spécifier le comportement de type nombre. Vous pouvez voir des exemples dans les types numériques dans le runtime .NET, par exemple System.Numerics.INumber<TSelf>. Ces interfaces définissent des opérateurs mathématiques courants implémentés par de nombreux types numériques. Le compilateur doit résoudre les appels aux méthodes static virtual
et static abstract
au moment de la compilation. Les méthodes static virtual
et static abstract
déclarées dans les interfaces n’ont pas de mécanisme de répartition d’exécution analogue aux méthodes virtual
ou abstract
déclarées dans les classes. Au lieu de cela, le compilateur utilise des informations de type disponibles au moment de la compilation. Par conséquent, les méthodes static virtual
sont presque exclusivement déclarées dans les interfaces génériques. En outre, la plupart des interfaces qui déclarent les méthodes static virtual
ou static abstract
notifient que l’un des paramètres de types doit implémenter l’interface déclarée. Par exemple, l’interface INumber<T>
déclare que T
doit implémenter INumber<T>
. Le compilateur utilise l’argument de type pour résoudre les appels aux méthodes et opérateurs déclarés dans la déclaration d’interface. Par exemple, le type int
implémente INumber<int>
. Lorsque le paramètre de type T
désigne l’argument de type int
, les membres static
déclarés dans int
sont appelés. Sinon, si double
est l’argument de type, les membres static
déclarés dans le type double
sont appelés.
Important
La répartition des méthodes static abstract
et static virtual
déclarées dans les interfaces est résolue à l’aide du type de temps de compilation d’une expression. Si le type d’exécution d’une expression est dérivé d’un type de temps de compilation différent, les méthodes statiques sur le type de base (heure de compilation) sont appelées.
Vous pouvez essayer cette fonctionnalité en travaillant avec le tutoriel sur les membres abstraits statiques dans les interfaces.
Héritage de l'interface
Les interfaces peuvent ne pas contenir d’état d’instance. Bien que les champs statiques soient désormais autorisés, les champs d’instance ne sont pas autorisés dans les interfaces. Les propriétés automatiques d’instance ne sont pas prises en charge dans les interfaces, car elles déclareraient implicitement un champ masqué. Cette règle a un effet subtil sur les déclarations de propriété. Dans une déclaration d’interface, le code suivant ne déclare pas une propriété implémentée automatiquement comme elle le fait dans un class
ou struct
. À la place, il déclare une propriété qui n’a pas d’implémentation par défaut, mais doit être implémentée dans n’importe quel type qui implémente l’interface :
public interface INamed
{
public string Name {get; set;}
}
Une interface peut hériter d’une ou de plusieurs interfaces de base. Quand une interface hérite d’une autre interface, un type implémentant l’interface dérivée doit implémenter tous les membres dans les interfaces de base, ainsi que ceux déclarés dans l’interface dérivée, comme illustré dans le code suivant :
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() { }
}
Lorsqu’une interface remplace une méthode implémentée dans une interface de base, elle doit utiliser la syntaxe d’implémentation d’interface explicite.
Lorsqu’une liste de types de base contient une classe de base et des interfaces, la classe de base doit figurer en premier dans la liste.
Une classe qui implémente une interface peut implémenter explicitement les membres de cette interface. Un membre implémenté explicitement n’est pas accessible via une instance de classe, mais uniquement via une instance de l’interface. En outre, les membres de l’interface par défaut sont accessibles uniquement via une instance de l’interface.
Pour plus d’informations sur l’implémentation d’interface explicite, consultez Implémentation d’interface explicite.
Exemple d’implémentation d’interface
L’exemple suivant montre une implémentation d’interface. Dans cet exemple, l’interface contient la déclaration de propriété, et la classe contient l’implémentation. Toutes les instances d’une classe qui implémentent IPoint
ont les propriétés entières x
et 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
spécification du langage C#
Pour plus d’informations, consultez la section Interfaces de la spécification du langage C#, la spécification de fonctionnalité pour C# 8 - Membres d’interface par défaut et la spécification de fonctionnalité pour C# 11 - Membres abstraits statiques dans les interfaces