通用接口隐藏父非通用接口方法

时间:2012-02-08 16:31:52

标签: c# .net

我想用通用接口IAppcontextItem实现泛型类AppContextItem。因为我想在List中存储多个AppContextItem而不知道确切的类型(并且我希望能够在列表中混合多个类型化的AppContextItem)。我创建了另一个非泛型接口IAppContextItem。 IAppContextItem的通用实现应该隐藏非泛型字段,但它不知道它,因为我得到一个编译错误,告诉我我需要实现带返回类型对象的元素。是不可能做我想做的事情或做错了什么?

IAppcontextItem.cs

public interface IAppContextItem
{

    string Key { get; set; }

    object Element { get; set; }

}

public interface IAppContextItem<T> : IAppContextItem 
    where T : class
{
    new string Key { get; set; }
    new T Element { get; set; }
}

AppContextItem.cs

public class AppContextItem<T> : IAppContextItem<T> where T : class
{

    private string key = string.Empty;
    private T element;

    public string Key
    {
        get { return key; }
        set { key = value; }
    }

    public T Element
    {
        get { return element; }
        set { element = value; }
    }

3 个答案:

答案 0 :(得分:4)

您必须同时实施T Elemen t和object Element属性。 object Element的实现如下:

object IAppContextItem.Element
{
   get; set;
}

然后您可以将其转换为正确的界面:

 AppContextItem<MainApp> app = new AppContextItem<MainApp>();
 IAppContextItem iapp = (IAppContextItem)app;
 object o = iapp.Element;

这称为Explicit Interface Implementation

如果您希望使用IAppContextItem.KeyIAppContextItem<T>.Key的不同实现,可以使用这样的显式接口实现:

string IAppContextItem.Key
{
    get { return key + "A"; }
    set { key = value; }
}

string IAppContextItem<T>.Key
{
    get { return key + "B"; }
    set { key = value; }
}

答案 1 :(得分:4)

这句话表明你的误解:

  

IAppContextItem的通用实现应该隐藏非泛型字段,但它不知道如何,因为我得到一个编译错误,告诉我需要用返回类型对象实现Element。

接口是合同;它说“需要这个接口的实现来提供以下方法和属性......”。 通过继承隐藏方法或财产既不符合合同的这一部分也不会消除合同对实施者施加的要求。

合同说要求提供四个属性。其中一些属性与其他属性具有相同的名称并不以任何方式消除您提供合同所描述的每个属性的要求。其中两个属性比其他两个属性“更明显”并不会改变合同需要四个属性的事实。你还是要实现所有四个;他们的知名度根本不会影响到它。

答案 2 :(得分:2)

Wouter de Kort的回答掩盖了一个重要的观点:如果你想让两个Element属性引用同一个对象,你就不能这样做:

object IAppContextItem.Element
{
    get; set;
}

如果这样做,您会发现您已为接口的Element属性创建了一个自动属性,该属性的值独立于T - 类型的Element属性。相反,你应该这样做:

object IAppContextItem.Element
{
    get { return this.Element; }
    set
    {
        if (!(value is T))
            throw // ... some exception
        this.Element = (T)value;
    }
}