在接口中包含扩展方法

本文关键字:扩展 方法 包含 接口 | 更新日期: 2023-09-27 18:03:48

当从一个具体类中抽象出一个接口时,该接口是否应该包含扩展方法?

在接口中包含扩展方法

就像你描述的那样,我会说不。如果您的扩展方法显然只在单元测试的上下文中有用,那么将它们作为测试项目中的扩展方法保留。

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

扩展方法对于向你无法控制的类添加功能或分离责任区域非常有用。

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

  • 将静态成员更改为可以成为接口一部分的实例成员
  • 将静态成员放在单独的扩展类(或其他依赖)中,以便SomeOtherClass可以替换为接口。

通过同时使用依赖的实例成员和静态成员,它有效地将两个依赖合二为一。您取决于对象(实例成员)和对象的类型(静态成员)

如果类本身需要这些方法才能发挥作用,那么它们应该是该类的成员。如果它们是为了让其他类以该类职责之外的方式使用该类而需要的(比如将一个类映射到另一个类的方法),那么我会将其分离出来。

如果方法是类和其他类都需要的,那么你可以把它分离成另一个类,原类和其他类都可以依赖。

举例来说,对于以下两个类:

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) { ... }
}

No。你在这方面有一些问题。首先,接口只描述公共实例方法的签名(也就是说,它们可能没有实现,你也不能在接口中指定静态方法)。扩展方法在编译时必须有一个实现,它们不是实例方法,而是静态方法。此时请注意,根据文档

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

换句话说,它不是真正的实例方法(即使你可以把它当作实例方法);在底层,它仍然是一个静态方法。

另外,扩展方法必须在静态类中定义(参见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();