使用泛型实现显式接口成员

时间:2011-09-28 16:43:19

标签: c# generics covariance

我有一个通用类组的非通用接口。我有一个方法,它使用协方差来返回从非泛型类组的抽象实现派生的类中的强类型实例。

所以基本上这个设置,我有很多类,例如ActualThing1ActualThing2。这些类有一个Clone方法,它返回一个强类型的克隆。

以下是我如何构建界面&类。我不确定这是对的。 通常,我根本就没有非泛型抽象类。但这是必要的,因为有一种情况我必须对子对象做一些事情,引用内部方法_SomethingNeededInternally。这不能使用接口来完成,因为它受保护,也不能从泛型类内部完成,因为子类可能不是同一类型(它们可能是从接口派生的不同类型)。因此,非通用基类Something

这是有效的,但对我来说没有意义的是我的抽象ISomething.Clone类中需要的Something的显式实现。它必须存在,但它不应该实现,因为我希望该实现延迟到派生自它的泛型类。但是没有abstract ISomething ISomething.Clone()这样的语法。

但是那个代码(抛出异常的地方)不能执行,可不可以,因为我没有这个对象的任何非泛型实现?

我想我想知道是否有更好的方法来做到这一点,因为它似乎不对。也就是说,我依赖于一个非泛型类永远不会从界面创建的事实,它闻起来很有趣。

public interface ISomething
{
    // ...
    ISomething Clone();
}

public abstract class Something: ISomething 
{
    ISomething ISomething.Clone()
    {
        throw new Exception("This should not be happening");
    }
    protected int _SomethingNeededInternally;
}

public abstract class Something<T>: Something, ISomething where T: ISomething, new()
{
    public abstract T Clone();

    ISomething ISomething.Clone()
    {
        return Clone();
    }
}

public interface IActualThing {} // this could be any interface

public class ActualThing: Something<ActualThing>, IActualThing
{
    public override ActualThing Clone() 
    {
        return new ActualThing(); // do cloning here
    }
}

5 个答案:

答案 0 :(得分:3)

为您添加所需的方法作为Clone的实现吗? (我仍然不确定你的整个问题是什么,这只会解决抽象显式接口实现的语法。)

public abstract class Something: ISomething  
{ 
    ISomething ISomething.Clone() 
    { 
        return CloneYouMust();
    } 
    abstract ISomething CloneYouMust();
}

答案 1 :(得分:2)

我认为这可能会更好:

public interface ISomething
{
    ISomething Clone();
}

public abstract class Something : ISomething 
{
    protected abstract ISomething CloneInternal();

    ISomething ISomething.Clone()
    {
        return CloneInternal();
    }
}

public abstract class Something<T>: Something, ISomething where T: ISomething, new()
{
    protected override ISomething CloneInternal()
    {
        return Clone();
    }

    public abstract T Clone();
}

public class ActualThing: Something<ActualThing>, IActualThing
{
    public override ActualThing Clone() 
    {
    }
}

答案 2 :(得分:0)

首先,我认为在Something&lt; T&gt;中有两个Clone()方法。是多余的。由于你已经将T限制为ISomething和new(),为什么不这样做:

public abstract class Something<T>: Something, ISomething 
       where T: ISomething, new() 
{     
    public override ISomething Clone()    
    {
        return new T().Clone(); 

        //alternatively may have to use Activator.CreateInstance() here
    }     
} 

其次,我并不完全清楚_SomethingNeededInternal是否需要是抽象的还是虚拟的,但它也没有标记。我的解释是它应该是虚拟的,但也许你需要调整它。无论如何,这里的总体方案对我来说似乎很有效并且最有意义。请注意,我能够在抽象类'Something'中使Clone()方法成为抽象:

public interface IActualThing
{
}

public interface ISomething 
{    
    ISomething Clone(); 
}  

public abstract class Something: ISomething  
{
    public abstract ISomething Clone();

    protected virtual void _SomethingNeededInternally()
    {
        throw new NotImplementedException(); 
    }
}  

public abstract class Something<T>: Something, ISomething where T: ISomething, new()
{    
    public override ISomething Clone()    
    {
        return new T().Clone(); 
    } 
}  

public class ActualThing: Something<ActualThing>, IActualThing 
{     
    public override ISomething Clone()      
    {
        throw new NotImplementedException(); 
    }
} 

另请注意,您需要在最终的'ActualThing'类中将返回类型标记为ISomething。当然,您实际上会返回'ActualThing',但该方法仍然需要符合界面。

答案 3 :(得分:0)

您对abstract ISomething ISomething.Clone的投诉是有效的,但没有关于表明您必须明确声明它们的接口。下面的代码显示了一个工作示例,并删除了泛型类的要求。

interface Igloo
{
    Igloo Clone();
}

abstract class Alpha : Igloo
{
    public abstract Igloo Clone();
}

class Bravo : Alpha
{
    public override Igloo Clone()
    {
        /* implement */
        return null;
    }
}

答案 4 :(得分:0)

我建议你定义和实现接口ISelf&lt; T&gt;,它包含一个T类型的Self属性,以及ICloneable&lt; out T&gt;,来自ISelf&lt; T&gt;,方法Clone()类型为T.然后是实现ICloneable&lt; ItsOwnType&gt;的类。可以使用返回ItsOwnType的方法实现它;该方法应该调用一个虚拟的InternalClone方法来完成实际工作(否则,在基类型变量上调用Clone可能最终会调用基类型Clone方法而不是派生方法)。