C# 在接口中包含扩展方法

C# 在接口中包含扩展方法,c#,.net,unit-testing,nunit,C#,.net,Unit Testing,Nunit,当从一个具体的类中抽象出一个接口时,该接口是否应该包含扩展方法?上下文专门用于易于单元测试。如果一个类依赖于SomeOtherClass,并且它同时依赖于SomeOtherClass的实例成员和静态成员,那么您可以 将静态成员更改为可以作为接口一部分的实例成员 将静态成员放在一个单独的扩展类(或某些其他依赖项)中,以便可以用接口替换SomeOtherClass 通过同时使用依赖项的实例成员和静态成员,它实际上变成了一个依赖项中的两个依赖项。这取决于对象(实例成员)和对象的类型(静态成员) 如

当从一个具体的类中抽象出一个接口时,该接口是否应该包含扩展方法?上下文专门用于易于单元测试。

如果一个类依赖于
SomeOtherClass
,并且它同时依赖于
SomeOtherClass
的实例成员和静态成员,那么您可以

  • 将静态成员更改为可以作为接口一部分的实例成员
  • 将静态成员放在一个单独的扩展类(或某些其他依赖项)中,以便可以用接口替换
    SomeOtherClass
通过同时使用依赖项的实例成员和静态成员,它实际上变成了一个依赖项中的两个依赖项。这取决于对象(实例成员)和对象的类型(静态成员)

如果类本身需要这些方法才能运行,那么它们很可能是该类的成员。如果为了让其他类以超出该类职责范围的方式使用该类而需要它们(比如将一个类映射到其他类的方法),那么我会将其分离出来


如果这些方法既为类所需,又为其他类所需,则可以将其拆分为原始类和其他类都可以依赖的另一个类。

否。您在这方面有一些问题。首先,接口仅描述公共实例方法的签名(即,它们可能没有实现,并且您可能没有在接口中指定静态方法)。扩展方法必须在编译时有一个实现,它们不是实例方法,而是静态方法。注意,在这一点上,根据

在代码中,使用实例方法调用扩展方法 语法。但是,由 编译器将代码转换为对静态方法的调用

换句话说,它不是一个真正的实例方法(即使你可以把它当作一个实例);“引擎盖下”仍然是一种静态方法

此外,必须在静态类中定义扩展方法(请参阅Microsoft的“如何实现扩展方法”)

请注意,您可以在接口上使用扩展方法;没有要求您扩展的类型是具体的。例如:

public static class Class2
{
    public static void Extension(this ITestInterface test)
    {
        Console.Out.WriteLine("This is allowed");
    }
}
现在,当我实例化一个实现ITestInterface接口的具体类时,我可以对其调用扩展方法:

// "Test" is some class that implements the ITestInterface interface
ITestInterface useExtensionMethod = new Test();
useExtensionMethod.Extension();

这可以满足您的需要。

例如,对于以下两个类:

class SomeClass
{
    public Prop1 { get; }
    public void Method1() { .... }
}

static class SomeExtensions
{
    public static ExtensionMethod(SomeClass this sc) { ... }
}
正如其他人所说,在创建接口时,您仅限于
SomeClass
中的公共非静态成员,但是,还需要修改扩展方法以引用接口,而不是同时引用具体类型:

static class SomeExtensions
{
    public static ExtensionMethod(ISomeClass this sc) { ... }
}

当您描述这个案例时,我会说不。如果您的扩展方法显然只在unittest的上下文中有用,那么将它们作为扩展方法保留在您的测试项目中

另一种方法是将扩展方法移动到类中(将它们更改为普通的公共方法),并将它们包含在接口中。这将使它们对使用类的所有对象都可用,这对于unittest代码来说是不可取的


扩展方法非常适合向您无法控制或无法划分责任区域的类添加功能。这是后者的一个典型例子。

不,那不行。如果接口声明了该方法,则类必须实现它。您可以使用特定的测试用例对扩展方法进行单元测试,因为它只是另一个类的静态方法。您的问题令人困惑,因为接口不能包含定义扩展方法所需的类。你是想问,带有扩展方法的类是否应该包含在与接口相同的文件中吗?是的,很好,我编辑了我的答案,以反映一个事实,即扩展方法也可以将接口作为参数类型-我认为这可以满足他的要求(即使接口本身并不真正包含扩展方法)。IMHO这可能比在具体类上使用扩展方法更好,这样您就可以根据接口而不是具体类进行编程。