【问题标题】:Generic and non-generic interfaces通用和非通用接口
【发布时间】:2012-07-13 15:01:13
【问题描述】:

我遇到过很多情况,我声明了一个泛型接口,后来我需要这个接口的非泛型版本,或者至少是该接口上某些方法或属性的非泛型版本。 我通常会声明一个新的非泛型接口并让它继承泛型接口。 我遇到的问题如下例所示:

public abstract class FormatBase { }

public interface IBook<F> where F : FormatBase
{
    F GetFormat();
}

public interface IBook
{
    object GetFormat();
}

public abstract class BookBase : IBook<FormatBase>, IBook
{
    public abstract FormatBase GetFormat();

    object IBook.GetFormat()
    {
        return GetFormat();
    }
}

既然声明 IBook(非泛型)接口的唯一方法是显式声明,那么你们如何将其抽象化?

【问题讨论】:

  • 这并不能解决您的问题,但您不认为将其设为BookBase&lt;T&gt; : IBook&lt;T&gt;, IBook where T : FormatBase 可能有意义吗?否则,至少在您的简单示例中,拥有IBook&lt;T&gt; 而不仅仅是IBook 几乎没有任何好处。
  • 你是对的。我更新代码。但是非泛型抽象的问题仍然存在。
  • 您还将获得一个“'IBook.GetFormat()' 隐藏继承的成员 'IBook.GetFormat()'。如果要隐藏,请使用新关键字。”警告。这可能是由于某处设计决策不佳,但如果没有更多信息,很难说出更好的设计会是什么。
  • 与你的问题无关,但也许你想让F中的通用接口协变,说public interface IBook&lt;out F&gt;
  • 我又做了一项更改以删除“使用新关键字...”消息。 IBook 不再从 IBook 继承。谢谢大家

标签: c# generics


【解决方案1】:

只是委托:

public abstract class BookBase : IBook<FormatBase> {
  public abstract FormatBase GetFormat();

  object IBook.GetFormat() {
    return GetFormat();
  }
}

或者,如果您仍然想区分这两种方法,请委托给一个新方法:

public abstract class BookBase : IBook<FormatBase> {
  public abstract FormatBase GetFormat();

  public abstract object IBook_GetFormat();

  object IBook.GetFormat() {
    return IBook_GetFormat();
  }
}

您还需要new 来躲避“隐藏继承的成员”警告:

public interface IBook<F> : IBook 
where F : FormatBase {
  new F GetFormat();
}

另外,让具体类决定具体的FormatBase 可能更有意义:

public abstract class BookBase<F> : IBook<F> 
where F : FormatBase {
  public abstract F GetFormat();

  object IBook.GetFormat() {
    return GetFormat();
  }
}

【讨论】:

  • @spender,我没有找到更好的方法,对吗?
  • @spender:使用 new 或更改名称...由于 OP 想要相同的名称,因此他使用 new 或收到警告...。我不知道你,但我不喜欢被警告我所做的故意决定......
  • 将此与 .NET 自己的接口 IEnumerable&lt;T&gt; 进行比较,该接口派生自 IEnumerable。它也有这个方法签名冲突(签名同意,返回类型不同意)。他们编译mscorlib的时候有这个警告,还是说new
  • 警告如果明确:“使用 new 关键字,如果隐藏的意图”。由于有意隐藏,new 的用法很好。
  • @JeppeStigNielsen:因为这是一个有意的决定,我敢打赌我的马(如果我有的话)他们使用new...
【解决方案2】:

为什么你不能写显式接口的实现,而不是声明它是抽象的?

public abstract class BookBase : IBook<FormatBase>, IBook
{                
    public abstract FormatBase GetFormat();

    object IBook.GetFormat()
    {
        return GetFormat();
    }
}

【讨论】:

  • 完美!这正是我想要的。
  • @Jordão 释放触发器 :)
  • @spender 这一行强制 BookBase 的继承者编写他们的 GetFormat 实现
  • @spender 我建议添加GetFormat 实现。就是这样:)
  • 哇,废话。我今天过得很糟糕。无视我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
  • 2023-01-28
相关资源
最近更新 更多