Tengo una DLL de C ++ de terceros a la que llamo desde C #.
Los métodos son estáticos.
Quiero abstraerlo para hacer algunas pruebas unitarias, así que creé una interfaz con los métodos estáticos, pero ahora mi programa tiene errores con:
El modificador 'estático' no es válido para este artículo
MyMethod cannot be accessed with an instance reference; qualify it with a type name instead
¿Cómo puedo lograr esta abstracción?
Mi código se ve así
private IInterfaceWithStaticMethods MyInterface;
public MyClass(IInterfaceWithStaticMethods myInterface)
{
this.MyInterface = myInterface;
}
public void MyMethod()
{
MyInterface.StaticMethod();
}
Respuestas:
No puede definir miembros estáticos en una interfaz en C #. Una interfaz es un contrato por instancias .
Recomendaría crear la interfaz como está actualmente, pero sin la palabra clave estática. Luego crea una clase
StaticIInterface
que implemente la interfaz y llame a los métodos estáticos de C ++. Para hacer pruebas unitarias, cree otra claseFakeIInterface
, que también implemente la interfaz, pero haga lo que necesita para manejar sus pruebas unitarias.Una vez que haya definido estas 2 clases, puede crear la que necesita para su entorno y pasarla al
MyClass
constructor de.fuente
An interface is a contract, not an implementation.
- eso es cierto, pero completamente irrelevante ( non sequitur ) aquí, ya que el método estático no es parte de la implementación en sí ; la implementación, por definición, se basa en datos , que, a su vez, son inaccesibles para los miembros estáticos.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.
- Tenga en cuenta que losstatic
miembros suelen ser métodos de utilidad .An interface is a contract, not an implementation
es inútil, a veces un poco de contextualización ayuda mucho. Y estoy totalmente de acuerdo con questatic method is not a part of implementation itself
los métodos estáticos tienen una implementación, se vuelven parte de la implementación solo si se usan como implementación en la implementación de otro método. Sin embargo, mi diccionario se basa en lo que aprendí, hasta donde yo sé, la terminología realmente varía también dependiendo del lenguaje de programación. Los métodos estáticos no pueden ser interfaces porque, de todos modos, solo puede haber una implementación.IPerson
contrato que establece queGetCountry
le dará el nombre del país de origen de la persona ...FrenchPerson
todas las entidades dirán "Francia" yGermanPerson
todas dirán "Alemania", también útil cuando diferentes tipos de entidades comparten la misma tabla (de datos), como MS Azure uno, digamosConnection
,Post
yComment
se almacenan enUsers
AzureTable, por lo que las entidades de árbol tienen una información compartida,IUsers
podrían tener unGetTableName
método estático ...Las interfaces no pueden tener miembros estáticos y los métodos estáticos no se pueden utilizar como implementación de métodos de interfaz.
Lo que puede hacer es utilizar una implementación de interfaz explícita:
public interface IMyInterface { void MyMethod(); } public class MyClass : IMyInterface { static void MyMethod() { } void IMyInterface.MyMethod() { MyClass.MyMethod(); } }
Alternativamente, puede simplemente usar métodos no estáticos, incluso si no acceden a ningún miembro específico de la instancia.
fuente
Los miembros estáticos son perfectamente legales en CLR, pero no C #.
Podría implementar algo de pegamento en IL para vincular los detalles de implementación.
Sin embargo, ¿no está seguro de si el compilador de C # permitiría llamarlos?
Consulte: 8.9.4 Definición del tipo de interfaz ECMA-335.
fuente
CLS Rule 19: CLS-compliant interfaces shall not define static methods, nor shall they define fields.
continúa diciendo que está bien que los consumidores que cumplen con CLS rechacen este tipo de interfaces. Intenté hace aproximadamente un año llamar a un método estático en una interfaz y el compilador de C # no lo compilaba.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.
tiene sentido que si el CLS se trata de la interoperabilidad entre diferentes lenguajes .NET, y C # no permite miembros estáticos en una interfaz, CLS también los prohibiría, para garantizar que las bibliotecas estén en otros lenguajes .NET se pueden llamar desde C #.Puede definir métodos estáticos en c # 8, pero debe declarar un cuerpo predeterminado para él.
public interface IMyInterface { static string GetHello() => "Default Hello from interface" ; static void WriteWorld() => Console.WriteLine("Writing World from interface"); }
o si no quieres tener ningún cuerpo predeterminado, simplemente lanza una excepción:
public interface IMyInterface { static string GetHello() => throw new NotImplementedException() ; static void WriteWorld() => throw new NotImplementedException(); }
fuente
Podrías invocarlo con reflexión:
MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);
fuente
C # "Ten" permitirá miembros estáticos en interfaces , junto con roles. Es un gran paso adelante, también permitirá la sobrecarga de operadores genéricos, sin ningún uso de reflexión. Aquí hay un fragmento de ejemplo de cómo funciona, utilizando el ejemplo clásico de monoide, que es solo jerga para decir "algo que se puede agregar". Tomado directamente de Mads Torgersen: C # en el futuro :
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
Recursos adicionales:
Jeremy Bytes: miembros estáticos de la interfaz C # 8
EDITAR
Esta publicación declaró originalmente que los miembros estáticos de la interfaz se agregarán en C # 8.0 , lo cual no es cierto, malinterpreté las palabras de Mads Torgersen en el video. La guía oficial de C # 8.0 aún no habla de los miembros de la interfaz estática, pero está claro que han estado trabajando en ella durante bastante tiempo.
fuente
En cuanto a por qué no puede tener un método estático en una interfaz: ¿Por qué C # no permite que los métodos estáticos implementen una interfaz?
Sin embargo, sugeriría eliminar los métodos estáticos en favor de los métodos de instancia. Si eso no es posible, entonces puede envolver las llamadas al método estático dentro de un método de instancia, y luego puede crear una interfaz para eso y ejecutar sus pruebas unitarias a partir de eso.
es decir
public static class MyStaticClass { public static void MyStaticMethod() {...} } public interface IStaticWrapper { void MyMethod(); } public class MyClass : IStaticWrapper { public void MyMethod() { MyStaticClass.MyStaticMethod(); } }
fuente
C # 8 permite miembros estáticos en interfaces
interfaz (referencia de C #)
P.ej
public interface IGetSomething { public static string Something = "something"; } var something = IGetSomething.Something;
fuente