J'ai une DLL C ++ tierce que j'appelle à partir de C #.
Les méthodes sont statiques.
Je veux l'abstraire pour faire des tests unitaires, j'ai donc créé une interface avec les méthodes statiques, mais maintenant mes erreurs de programme avec:
Le modificateur «statique» n'est pas valide pour cet article
MyMethod cannot be accessed with an instance reference; qualify it with a type name instead
Comment puis-je réaliser cette abstraction?
Mon code ressemble à ceci
private IInterfaceWithStaticMethods MyInterface;
public MyClass(IInterfaceWithStaticMethods myInterface)
{
this.MyInterface = myInterface;
}
public void MyMethod()
{
MyInterface.StaticMethod();
}
Réponses:
Vous ne pouvez pas définir de membres statiques sur une interface en C #. Une interface est un contrat pour les instances .
Je recommanderais de créer l'interface telle que vous l'êtes actuellement, mais sans le mot-clé static. Créez ensuite une classe
StaticIInterface
qui implémente l'interface et appelle les méthodes C ++ statiques. Pour faire des tests unitaires, créez une autre classeFakeIInterface
, qui implémente également l'interface, mais fait ce dont vous avez besoin pour gérer vos tests unitaires.Une fois ces 2 classes définies, vous pouvez créer celle dont vous avez besoin pour votre environnement et la transmettre au
MyClass
constructeur de.la source
An interface is a contract, not an implementation.
- c'est vrai, mais complètement hors de propos ( non sequitur ) ici, puisque la méthode statique ne fait pas partie de l'implémentation elle - même - l'implémentation, par définition, est basée sur des données , qui sont, à leur tour, inaccessibles pour les membres statiques.An interface type definition can define and implement static methods (see §8.4.3) since static methods are associated with the interface type itself rather than with any value of the type.
- gardez à l'esprit que lesstatic
membres sont généralement des méthodes d'utilité .An interface is a contract, not an implementation
c'est inutile, parfois un peu de contextualisation aide vraiment. Et je suis tout à fait d'accord avecstatic method is not a part of implementation itself
, les méthodes statiques ont une implémentation, elles ne font partie de l'implémentation que si elles sont utilisées comme implémentation dans l'implémentation d'une autre méthode. Cependant, mon dictionnaire est basé sur ce que j'ai appris, pour autant que je sache, la terminologie varie vraiment aussi en fonction du langage de programmation. Les méthodes statiques ne peuvent pas être des interfaces car il ne peut y avoir qu'une seule implémentation.IPerson
contrat qui stipule queGetCountry
je donne le nom du pays d'origine de la personne ... lesFrenchPerson
entités diront toutes «France» etGermanPerson
toutes diront «Allemagne», également utile lorsque différents types d'entités partagent le même tableau (de données), comme MS Azure one, disonsConnection
,Post
etComment
sont stockés dansUsers
AzureTable, donc les entités d'arborescence ont une information partagée,IUsers
pourraient avoirGetTableName
une méthode statique ...Les interfaces ne peuvent pas avoir de membres statiques et les méthodes statiques ne peuvent pas être utilisées comme implémentation de méthodes d'interface.
Ce que vous pouvez faire, c'est utiliser une implémentation d'interface explicite:
public interface IMyInterface { void MyMethod(); } public class MyClass : IMyInterface { static void MyMethod() { } void IMyInterface.MyMethod() { MyClass.MyMethod(); } }
Sinon, vous pouvez simplement utiliser des méthodes non statiques, même si elles n'accèdent à aucun membre spécifique à une instance.
la source
Les membres statiques sont parfaitement légaux dans le CLR, mais pas C #.
Vous pouvez implémenter un peu de glue dans IL pour relier les détails d'implémentation.
Vous ne savez pas si le compilateur C # permettrait de les appeler?
Voir: 8.9.4 Définition du type d'interface ECMA-335.
la source
CLS Rule 19: CLS-compliant interfaces shall not define static methods, nor shall they define fields.
il poursuit en disant qu'il est normal que les consommateurs conformes CLS rejettent ces types d'interfaces. J'ai essayé il y a environ un an d'appeler une méthode statique sur une interface et le compilateur C # ne la compilait pas.Common Language Specification (CLS) is a set of basic language features that .Net Languages needed.... When there is a situation to communicate Objects written in different .Net Complaint languages , those objects must expose the features that are common to all the languages.
il est logique que si le CLS concerne l'interopérabilité entre différents langages .NET et que C # n'autorise pas les membres statiques sur une interface, alors le CLS les interdirait également, pour garantir les bibliothèques dans d'autres langages .NET peuvent être appelés à partir de C #.Vous pouvez définir des méthodes statiques en c # 8 mais vous devez déclarer un corps par défaut pour cela.
public interface IMyInterface { static string GetHello() => "Default Hello from interface" ; static void WriteWorld() => Console.WriteLine("Writing World from interface"); }
ou si vous ne voulez pas de corps par défaut, lancez simplement une exception:
public interface IMyInterface { static string GetHello() => throw new NotImplementedException() ; static void WriteWorld() => throw new NotImplementedException(); }
la source
Vous pouvez l'invoquer avec réflexion:
MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);
la source
C # "Ten" va autoriser les membres statiques sur les interfaces , avec les rôles. C'est un énorme pas en avant, cela permettra également une surcharge des opérateurs génériques, sans aucune réflexion. Voici un extrait d'exemple de son fonctionnement, en utilisant l'exemple classique du monoïde, qui n'est qu'un jargon pour dire "quelque chose qui peut être ajouté". Tiré directement de Mads Torgersen: C # into the Future :
interface IMonoid<T> { static T Zero { get; } static T operator +(T t1, T t2); } public static T AddAll<T>(T[] ts) where T : IMonoid<T> { T result = T.Zero; foreach (T t in ts) { result += t; } return result; } role IntAddMonoid extends int : IMonoid<int> { public static int Zero => 0; } IntAddMonoid[] values = new int[] {1, 2, 4, 8, 16, 32}; int sixtyThree = AddAll<IntAddMonoid>(values); // == 63
Ressources additionnelles:
Jeremy Bytes: membres statiques de l'interface C # 8
ÉDITER
Ce message a initialement déclaré que les membres statiques de l'interface seront ajoutés dans C # 8.0 , ce qui n'est pas vrai, j'ai mal interprété les mots de Mads Torgersen dans la vidéo. Le guide officiel C # 8.0 ne parle pas encore des membres de l'interface statique, mais il est clair qu'ils y travaillent depuis assez longtemps.
la source
Quant à savoir pourquoi vous ne pouvez pas avoir de méthode statique sur une interface: Pourquoi C # n'autorise-t-il pas les méthodes statiques à implémenter une interface?
Cependant, je suggérerais de supprimer les méthodes statiques au profit des méthodes d'instance. Si cela n'est pas possible, vous pouvez encapsuler les appels de méthode statique à l'intérieur d'une méthode d'instance, puis créer une interface pour cela et exécuter vos tests unitaires à partir de cela.
c'est à dire
public static class MyStaticClass { public static void MyStaticMethod() {...} } public interface IStaticWrapper { void MyMethod(); } public class MyClass : IStaticWrapper { public void MyMethod() { MyStaticClass.MyStaticMethod(); } }
la source
C # 8 autorise les membres statiques sur les interfaces
interface (référence C #)
Par exemple
public interface IGetSomething { public static string Something = "something"; } var something = IGetSomething.Something;
la source