【问题标题】:Generic Interface hiding of parent non-generic interface methods父非泛型接口方法的泛型接口隐藏
【发布时间】:2012-03-01 03:11:19
【问题描述】:

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

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; }
    }

【问题讨论】:

  • 我不明白你为什么要实现这两个接口,因为通用的就足够了。唯一的区别是 Element 属性的类型;你没有从非通用接口中获得任何收益。
  • 你是对的,看看我对 Wouter de Kort 答案的评论。

标签: c# .net


【解决方案1】:

您必须同时实现 T Element 和 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.Key 和IAppContextItem&lt;T&gt;.Key 的不同实现,你可以像这样使用显式接口实现:

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

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

【讨论】:

  • 这解决了我的问题,谢谢!对于每个在类似问题上苦苦挣扎的人。我按照 jmpcm 的建议删除了通用接口,并按照 Wouter de Kort 的建议将对象 IAppContextItem.Element 添加到了 AppContextItem 中。不要忘记在 IAppContextItem.Element 的实现中仍然填写 getter 和 setter 的值。否则,当您将 AppContextItem 转换为 IAppcontextItem 并想要访问该值时,您会遇到问题。
【解决方案2】:

这句话表明你的误解:

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

接口是契约;它说“这个接口的实现需要提供以下方法和属性......”。 通过继承隐藏方法或属性既不履行合同的那一部分,也不消除合同对实施者的要求。

合同规定实现需要提供四个属性。其中一些属性与其他属性具有相同的名称并不会以任何方式消除您提供合同描述的每个属性的要求。其中两个属性比其他两个“更明显”并没有改变合同需要四个属性的事实。您仍然必须实现所有四个;他们的知名度根本不考虑在内。

【讨论】:

    【解决方案3】:

    Wouter de Kort 的回答掩盖了一个重要点:如果您希望两个 Element 属性都引用同一个对象,则不能这样做:

    object IAppContextItem.Element
    {
        get; set;
    }
    

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

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

    【讨论】:

      猜你喜欢
      • 2017-11-13
      • 2016-12-14
      • 2011-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多