Partage via


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 :

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

Voir aussi