是否有可能强制接口实现在C#中是虚拟的?

时间:2012-07-03 10:41:34

标签: c# inheritance interface

我今天遇到了一个问题,试图覆盖一个尚未声明为虚拟的接口方法的实现。

在这种情况下,我无法更改接口或基本实现,必须尝试其他方法,但我想知道是否有办法强制类使用虚方法实现接口。

示例:

interface IBuilder<T>
{
    // Already implicitly virtual
    /*virtual*/ T Build();
}

// This is a class written by someone else
class SimpleBuilder: IBuilder<SomeObject>
{
    // I would like to force this to be virtual
    public SomeObject Build() { return new SomeObject(); }
}

// This is the class I am writing.
class CustomBuilder: SimpleBuilder
{
    public /*override*/ SomeObject Build()
    {
        var obj = base.Build();
        obj.ModifyInSomeWay();
        return obj;
    }
}

编辑:CustomBuilder旨在与MEF一起使用,因此我从SimpleBuilder派生,以便MEF解析正确的类型。我已经尝试过显式实现接口,而不是从SimpleBuilder派生,但MEF没有选择正确的类型。

有问题的接口和基类位于另一个开发人员创建的共享模块中,所以看起来我必须让他们改变他们的基类。

5 个答案:

答案 0 :(得分:3)

在你的例子中没有,你是implicitly implementing界面。如果您的类要进行子类化并且方法被覆盖,则由开发人员确保该方法被标记为虚拟。

没有办法强制在代码中重写接口方法的实现,只有开发团队中的约定才能确保这一点(例如,所有接口都应该显式实现,所有接口实现都应该标记为虚拟等)。

在此特定示例中,您可以将抽象类插入层次结构中:

abstract class VirtualBuilder<T> : IBuilder<T>
{
  abstract T Build();
}

但是这不适用于通用情况,因为你失去了接口的好处并且“强制”所有具体的类只能实现一个接口。

答案 1 :(得分:2)

不直接,没有。

你可以通过提供自己的基类来强制它,并要求用户从中派生出来:

abstract class BuilderBase<T> : IBuilder<T>
{
    public abstract T Build();
}

但这也有严重的问题因为

  1. 它不会立即阻止任何人直接实现界面(尽管您可以要求传入参数为BuilderBase<T>而不是简单IBuilder<T>,甚至可以IBuilder<T> {{1}并将其隐藏在另一个程序集中)
  2. 它迫使界面的实施者放弃他们对单一基类的选择,他们可能会讨厌你

答案 2 :(得分:1)

你不能强制它是虚拟的,但你可以使用new关键字;它被称为Method Hiding

// This is the class I am writing. 
class CustomBuilder: SimpleBuilder, IBuilder<T> 
{ 
    public new SomeObject Build() 
    { 
        var obj = base.Build(); 
        obj.ModifyInSomeWay(); 
        return obj; 
    } 
} 

答案 3 :(得分:0)

无法指定如何实现接口方法。

但是,即使基本实现不是虚拟的,您也有两种方法可以重新实现子类上的接口方法:

  • 使用new方法限定符或
  • 隐藏基本实现
  • 显式接口实现如下:

    T IBuilder.Build()  {      var obj = Build();      obj.ModifyInSomeWay();      返回obj;  }

这两种方法中的任何一种都将确保只有在通过接口访问类时才调用您的方法,但如果调用使用基类引用则不会。

所以我想说这个基类还没有为继承扩展做好准备。

答案 4 :(得分:0)

你不能这样做,因为Inteface只描述了一个类应该是什么样子,并且没有说明实现本身。

换句话说,如果你使用一个实现定义方法Foo()的接口的类,你可以肯定,无论实现如何,该类都有这个方法。

你能做什么:

public interface IBuilder<T>
{
    T Build();
}

public abstract class BaseBuilder<T> : IBuilder<T>
{
    public abstract T Build();
}

public class CustomBuilder : BaseBuilder<CustomBuilder>
{
    public override CustomBuilder Build()
    {
        throw new NotImplementedException();
    }
}