如何在接口上实现静态方法?

时间:2022-05-27 08:08:48

I have a 3rd party C++ DLL that I call from C#.

我有一个第三方c++ DLL,我从c#调用。

The methods are static.

是静态的方法。

I want to abstract it out to do some unit testing so I created an interface with the static methods in it but now my program errors with:

我想把它抽象出来做一些单元测试,所以我创建了一个接口,其中包含静态方法,但是现在我的程序错误如下:

The modifier 'static' is not valid for this item

修饰符“static”对该条目无效

MyMethod cannot be accessed with an instance reference; qualify it with a type name instead

How can I achieve this abstraction?

我如何实现这个抽象?

My code looks like this

我的代码是这样的。

private IInterfaceWithStaticMethods MyInterface;

public MyClass(IInterfaceWithStaticMethods myInterface)
{
  this.MyInterface = myInterface;
}

public void MyMethod()
{
  MyInterface.StaticMethod();
}

5 个解决方案

#1


20  

You can't define static members on an interface in C#. An interface is a contract for instances.

您不能在c#中定义接口上的静态成员。接口是实例的契约。

I would recommend creating the interface as you are currently, but without the static keyword. Then create a class StaticIInterface that implements the interface and calls the static C++ methods. To do unit testing, create another class FakeIInterface, that also implements the interface, but does what you need to handle your unit tests.

我建议像现在这样创建接口,但是不要使用静态关键字。然后创建一个实现接口的类StaticIInterface,并调用静态c++方法。要执行单元测试,请创建另一个类FakeIInterface,它也实现接口,但是执行处理单元测试所需的操作。

Once you have these 2 classes defined, you can create the one you need for your environment, and pass it to MyClass's constructor.

一旦定义了这两个类,就可以创建环境所需的类,并将其传递给MyClass的构造函数。

#2


56  

Interfaces can't have static members and static methods can not be used as implementation of interface methods.

接口不能有静态成员,静态方法不能作为接口方法的实现。

What you can do is use an explicit interface implementation:

你所能做的就是使用一个明确的接口实现:

public interface IMyInterface
{
    void MyMethod();
}

public class MyClass : IMyInterface
{
    static void MyMethod()
    {
    }

    void IMyInterface.MyMethod()
    {
        MyClass.MyMethod();
    }
}

Alternatively, you could simply use non-static methods, even if they do not access any instance specific members.

或者,您可以简单地使用非静态方法,即使它们不访问任何实例特定的成员。

#3


12  

Static members are perfectly legal in the CLR, just not C#.

静态成员在CLR中是完全合法的,而不是c#。

You could implement some glue in IL to link up the implementation details.

您可以在IL中实现一些glue来链接实现细节。

Not sure if the C# compiler would allow calling them though?

不确定c#编译器是否允许调用它们?

See: 8.9.4 Interface type definition ECMA-335.

参见:8.9.4接口类型定义

Interface types are necessarily incomplete since they say nothing about the representation of the values of the interface type. For this reason, an interface type definition shall not provide field definitions for values of the interface type (i.e., instance fields), although it can declare static fields (see §8.4.3).

接口类型必然是不完整的,因为它们不涉及接口类型的值的表示。因此,接口类型定义不应为接口类型的值提供字段定义(即实例字段),尽管它可以声明静态字段(参见§8.4.3)。

Similarly, an interface type definition shall not provide implementations for any methods on the values of its type. However, an interface type definition can—and usually does—define method contracts (method name and method signature) that shall be implemented by supporting types. 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.

类似地,接口类型定义不应为其类型的值提供任何方法的实现。然而,接口类型定义可以(通常是)定义方法契约(方法名称和方法签名),由支持类型实现。一个接口类型定义可以定义和实现静态方法(见§8.4.3)由于静态方法与接口类型本身有关,而与任何值的类型。

#4


5  

You could invoke it with reflection:

您可以通过反思来调用它:

MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);

#5


0  

As to why you cannot have a static method on an interface: Why Doesn't C# Allow Static Methods to Implement an Interface?

至于为什么不能在接口上使用静态方法:为什么c#不允许静态方法实现接口?

However, I would suggest removing the static methods in favor of instance methods. If that is not possible, then you could wrap the static method calls inside of an instance method, and then you can create an interface for that and run your unit tests from that.

但是,我建议删除静态方法,而使用实例方法。如果这是不可能的,那么您可以将静态方法调用封装到实例方法中,然后您可以为该方法创建一个接口,并从中运行单元测试。

ie

public static class MyStaticClass
{
    public static void MyStaticMethod()
    {...}
}

public interface IStaticWrapper
{
    void MyMethod();
}

public class MyClass : IStaticWrapper
{
    public void MyMethod()
    {
        MyStaticClass.MyStaticMethod();
    }
}

#1


20  

You can't define static members on an interface in C#. An interface is a contract for instances.

您不能在c#中定义接口上的静态成员。接口是实例的契约。

I would recommend creating the interface as you are currently, but without the static keyword. Then create a class StaticIInterface that implements the interface and calls the static C++ methods. To do unit testing, create another class FakeIInterface, that also implements the interface, but does what you need to handle your unit tests.

我建议像现在这样创建接口,但是不要使用静态关键字。然后创建一个实现接口的类StaticIInterface,并调用静态c++方法。要执行单元测试,请创建另一个类FakeIInterface,它也实现接口,但是执行处理单元测试所需的操作。

Once you have these 2 classes defined, you can create the one you need for your environment, and pass it to MyClass's constructor.

一旦定义了这两个类,就可以创建环境所需的类,并将其传递给MyClass的构造函数。

#2


56  

Interfaces can't have static members and static methods can not be used as implementation of interface methods.

接口不能有静态成员,静态方法不能作为接口方法的实现。

What you can do is use an explicit interface implementation:

你所能做的就是使用一个明确的接口实现:

public interface IMyInterface
{
    void MyMethod();
}

public class MyClass : IMyInterface
{
    static void MyMethod()
    {
    }

    void IMyInterface.MyMethod()
    {
        MyClass.MyMethod();
    }
}

Alternatively, you could simply use non-static methods, even if they do not access any instance specific members.

或者,您可以简单地使用非静态方法,即使它们不访问任何实例特定的成员。

#3


12  

Static members are perfectly legal in the CLR, just not C#.

静态成员在CLR中是完全合法的,而不是c#。

You could implement some glue in IL to link up the implementation details.

您可以在IL中实现一些glue来链接实现细节。

Not sure if the C# compiler would allow calling them though?

不确定c#编译器是否允许调用它们?

See: 8.9.4 Interface type definition ECMA-335.

参见:8.9.4接口类型定义

Interface types are necessarily incomplete since they say nothing about the representation of the values of the interface type. For this reason, an interface type definition shall not provide field definitions for values of the interface type (i.e., instance fields), although it can declare static fields (see §8.4.3).

接口类型必然是不完整的,因为它们不涉及接口类型的值的表示。因此,接口类型定义不应为接口类型的值提供字段定义(即实例字段),尽管它可以声明静态字段(参见§8.4.3)。

Similarly, an interface type definition shall not provide implementations for any methods on the values of its type. However, an interface type definition can—and usually does—define method contracts (method name and method signature) that shall be implemented by supporting types. 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.

类似地,接口类型定义不应为其类型的值提供任何方法的实现。然而,接口类型定义可以(通常是)定义方法契约(方法名称和方法签名),由支持类型实现。一个接口类型定义可以定义和实现静态方法(见§8.4.3)由于静态方法与接口类型本身有关,而与任何值的类型。

#4


5  

You could invoke it with reflection:

您可以通过反思来调用它:

MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);

#5


0  

As to why you cannot have a static method on an interface: Why Doesn't C# Allow Static Methods to Implement an Interface?

至于为什么不能在接口上使用静态方法:为什么c#不允许静态方法实现接口?

However, I would suggest removing the static methods in favor of instance methods. If that is not possible, then you could wrap the static method calls inside of an instance method, and then you can create an interface for that and run your unit tests from that.

但是,我建议删除静态方法,而使用实例方法。如果这是不可能的,那么您可以将静态方法调用封装到实例方法中,然后您可以为该方法创建一个接口,并从中运行单元测试。

ie

public static class MyStaticClass
{
    public static void MyStaticMethod()
    {...}
}

public interface IStaticWrapper
{
    void MyMethod();
}

public class MyClass : IStaticWrapper
{
    public void MyMethod()
    {
        MyStaticClass.MyStaticMethod();
    }
}