泛型IAbstract <t>继承自IAbstract </t>

时间:2014-05-18 17:22:33

标签: c# generics

我正在努力实现这样的目标:

interface IAbstract
{
    string A { get; }
    object B { get; }
}

interface IAbstract<T> : IAbstract
{
    T B { get; }
}

class RealThing<T> : IAbstract<T>
{
    public string A { get; private set; }
    public T B { get; private set; }
}

所以我可以这样做:

RealThing<string> rt = new RealThing<string>();
IAbstract ia = rt;
IAbstract<string> ias = rt;
object o = ia.B;
string s = ias.B;

这可能吗?

4 个答案:

答案 0 :(得分:10)

非常接近。三件事:

  • 您应该使用new中的IAbstract<T>表示您知道自己隐藏了现有成员:

    new T B { get; }
    

    但即便没有,你仍然只会收到警告。

  • 您需要在IAbstract.B中实现RealThing,您几乎肯定会使用显式接口实现,委托给强类型成员:

    object IAbstract.B { get { return B; } }
    
  • 在测试代码中,您需要为RealThing指定类型参数:

    RealThing<string> rt = new RealThing<string>();
    

这很好,甚至是一个相当常见的模式,适合您希望能够获得非泛型形式的界面。

答案 1 :(得分:7)

是的,几乎没有变化

interface IAbstract
{
    string A { get; }
    object B { get; }
}

interface IAbstract<T> : IAbstract
{
    new T B { get; }
}

sealed class RealThing<T> : IAbstract<T>
{
    public string A { get; private set; }
    public T B { get; private set; }

    object IAbstract.B
    {
        get { return B; }
    }
}

所以你可以写

var rt = new RealThing<string>();
IAbstract ia = rt;
IAbstract<string> ias = rt;
object o = ia.B;
string s = ias.B;

答案 2 :(得分:1)

实际上System.Collections.IEnumeratorSystem.Collections.IEnumerator<T>接口就是这样做的。实施IEnumerable<T>时,您必须明确实施其中一个Current属性,通常您会选择非通用属性:

object IEnumerable.Current
{
    // this calls the implicitly implemented generic property
    get { return this.Current; }
}

public T Current
{
    get { return this.current; } // or however you want to do it
}

答案 3 :(得分:1)

在这种情况下,您甚至不需要两个接口。只需将接口标记为协变(从C#4开始支持):

interface IAbstract<out T>
{
    string A { get; }
    T B { get; }
}

并在之前使用非通用接口的任何地方使用IAbstract<object>