web-dev-qa-db-fra.com

Appel de méthode statique d'interface C # avec des génériques

Existe-t-il un moyen simple d'implémenter cela, et si possible sans instancier un objet:

interface I
{
     static  string GetClassName();
}

public class Helper
{

    static void PrintClassName<T>() where T : I
    {
         Console.WriteLine(T.GetClassName());
    }
}
27
Toto

Essayez plutôt une méthode d'extension:

public interface IMyInterface
{
     string GetClassName();
}

public static class IMyInterfaceExtensions
{
    public static void PrintClassName<T>( this T input ) 
        where T : IMyInterface
    {
         Console.WriteLine(input.GetClassName());
    }
}

Cela vous permet d'ajouter une méthode d'extension/utilitaire statique, mais vous avez toujours besoin d'une instance de votre implémentation IMyInterface.

Vous ne pouvez pas avoir d'interfaces pour les méthodes statiques car cela n'aurait aucun sens, ce sont des méthodes utilitaires sans instance et, par conséquent, elles n'ont pas vraiment de type.

24
Keith

Vous ne pouvez pas hériter de méthodes statiques. Votre code ne compilerait en aucune manière, car une interface ne peut pas avoir de méthodes statiques à cause de cela.

Comme cité de littleguru :

L'héritage dans .NET ne fonctionne que sur une base d'instance. Les méthodes statiques sont définies au niveau du type et non au niveau de l'instance. C'est pourquoi la substitution ne fonctionne pas avec les méthodes/propriétés/événements statiques ...

Les méthodes statiques ne sont conservées qu'une seule fois en mémoire. Aucune table virtuelle, etc. n'a été créée pour eux.

Si vous appelez une méthode d'instance dans .NET, vous lui indiquez toujours l'instance actuelle. Ceci est caché par le runtime .NET, mais cela arrive. Chaque méthode d'instance a comme premier argument un pointeur (référence) sur l'objet sur lequel la méthode est exécutée. Cela ne se produit pas avec les méthodes statiques (telles qu'elles sont définies au niveau du type). Comment le compilateur doit-il décider de sélectionner la méthode à appeler?

7
Dykam

J'ai également essayé de configurer une méthode statique sur une interface il y a un moment, sans savoir pourquoi maintenant. J'ai fait un signet, alors peut-être que ça aide:

Interface avec une méthode statique à l'aide de méthodes d'extension

3
Nick Clarke

Si vous êtes juste après le nom du type, vous pouvez simplement faire ceci:

public class Helper
{
    static void PrintClassName<T>()
    {
         Console.WriteLine(typeof(T).Name);
    }
}
3
Kent Boogaart

Déclarer une staticproperty, event ou method dans une définition d'interface n'est pas considéré comme une définition légale. En effet, les interfaces sont considérées comme des contrats et représentent donc quelque chose qui sera sera implémenté par chaque instance client de cette interface.

Une déclaration static indique essentiellement que le membre static ne nécessite pas d'implémentation de client physique pour exécuter la fonctionnalité requise, ce qui est en deçà du concept général d'interfaces: fournir un contrat prouvé.

2
Mike J

La réponse est un qualifié "pas vraiment mais Sort Of". Vous pouvez fournir une méthode d'extension statique à tous les implémenteurs d'une interface donnée et l'appeler ensuite à partir de votre implémenteur dans une propriété ou une autre méthode. Par exemple:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InterfacesWithGenerics
{
    class Program
    {
        static void Main(string[] args)
        {
            Helper.PrintClassName<Example>(new Example());
            Console.ReadLine();
        }
    }

    public class Example : I
    {
        #region I Members

        public string ClassName
        {
            get { return this.GetClassName(); }
        }

        #endregion
    }

    public interface I
    {
        string ClassName { get; }
    }

    public class Helper
    {

        public static void PrintClassName<T>(T input) where T : I
        {           
            Console.WriteLine( input.GetClassName()) ;
        }
    }

    public static class IExtensions
    {
        public static string GetClassName(this I yourInterface)
        {
            return yourInterface.GetType().ToString();
        }
    }
}

Nous avons ici une interface (I) qui définit la propriété qui nous intéresse et une méthode d’extension statique (GetClassName) qui est appliquée à tous les membres de son type et qui effectue le travail fastidieux pour obtenir les informations souhaitées. Nous avons une classe (exemple) qui implémente l'interface I; ainsi, lorsque nous appelons notre classe d'assistance statique en passant dans une instance de Example, elle exécute la méthode statique. Malheureusement, il n'est pas valide de référencer le type T directement dans la méthode elle-même en tant que variable, vous devrez passer une instance dans l'application.

1
Wolfwyrd

Vous pouvez définir le className en tant qu'attribut sur la classe spécifique. C’est l’option par défaut pour stocker les métadonnées dans .net. De cette façon, vous pouvez interroger l'attribut pour la classe donnée et vous n'avez pas besoin d'instance.

0
codymanix