在接口中声明成员函数

van*_*nna 9 c# interface member

首先,我是C#的新手.我想有一个接口声明一个成员函数,如下面的代码片段

interface IMyInterface {
    void MyAction() {
        // do stuff depending on the output of function()
    }
    void Function();
}
Run Code Online (Sandbox Code Playgroud)

这里Function是纯粹的虚拟,应该由孩子们实施IMyInterface.我可以使用抽象类而不是接口,但后来我无法从其他类继承...例如,MyAction在递归搜索目录中的文件并应用于Function任何找到的文件以使我的示例清晰.

如何更改我的设计以克服接口无法实现类的约束?

编辑:在C++中,我要做的就是使用模板

template<class A>
static void MyAction(const A& a) {
    // do stuff depending on the output of A::Function()
};

class MyClass {
    void Function();
};
Run Code Online (Sandbox Code Playgroud)

我想知道是否有一种优雅的方式来使用C#中的接口来做到这一点.

Ree*_*sey 11

直接处理这个问题的唯一方法是使用抽象类,因为接口不能包含任何形式的"逻辑",而只是一个契约.

然而,一种替代方案是创建接口和静态类.然后,您可以使用界面将逻辑放在扩展方法中.

public interface IMyInterface {
    void Function();
}

public static class MyInterfaceExtensions {
    public static void MyAction(this IMyInterface object)
    {
       // use object.Function() as needed
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的主要缺点是更多类型,这降低了可维护性,并且缺乏可发现性.

  • +1提及经常被忽视的使用扩展方法实现接口功能的替代方案. (3认同)
  • @dasblinkenlight然而我担心一个全新的C#用户可能无法理解扩展方法和真实实例方法之间的区别.如果您不了解它们的不同之处,它可能会导致问题. (3认同)

Oli*_*bes 10

在C#中,您没有多重继承.您可以通过使用合成来规避此限制.

像这样定义你的界面(Function这里不需要定义):

public interface IMyInterface
{
    void MyAction();
}
Run Code Online (Sandbox Code Playgroud)

使用抽象声明一个抽象类Function并实现此接口:

public abstract class MyInterfaceBase : IMyInterface
{
    public void MyAction()
    {
        // Do stuff depending on the output of Function().
        Function();
    }

    protected abstract void Function();
}
Run Code Online (Sandbox Code Playgroud)

从这个抽象类中,您可以派生出具体的实现.这还不是你的"最终"类,但它将被用来组成它.

public class ConcreteMyInterface : MyInterfaceBase
{
    protected override void Function()
    {
        Console.WriteLine("hello");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在让我们来到你的"最后",写作课.它将通过集成以下功能来SomeBaseClass实现和实现:IMyInterfaceConcreteMyInterface

public class SomeBaseClass
{
}

public class MyComposedClass : SomeBaseClass, IMyInterface
{
    private readonly IMyInterface _myInterface = new ConcreteMyInterface();

    public void MyAction()
    {
        _myInterface.MyAction();
    }
}
Run Code Online (Sandbox Code Playgroud)

UPDATE

在C#中,您可以声明本地类.这更接近于多重继承,因为您可以在编写类中派生所有内容.

public class MyComposedClass : SomeBaseClass, IMyInterface
{
    private readonly IMyInterface _myInterface = new ConcreteMyInterface();

    public void MyAction()
    {
        _myInterface.MyAction();
    }

    private class ConcreteMyInterface : MyInterfaceBase
    {
        protected override void Function()
        {
            Console.WriteLine("hello");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


dtb*_*dtb 7

您可以定义MyAction扩展方法:

public interface IMyInterface
{
   void Function();
}

public static class MyInterfaceExtensions
{
    public static void MyAction(this IMyInterface obj)
    {
        obj.Function();
    }
}
Run Code Online (Sandbox Code Playgroud)

例:

public class HelloWorld : IMyInterface
{
    public void Function()
    {
        Console.WriteLine("Hello World");
    }

    public static void Main(string[] args)
    {
        new HelloWorld().MyAction();
    }
} 
Run Code Online (Sandbox Code Playgroud)

输出:

Hello World