具有通用子类型的抽象类

时间:2015-03-07 12:32:42

标签: c# .net generics override abstract-class

我实现了如下的抽象类:

public abstract class Pack
{
    protected List<PackEntry> m_Entries;

    public Int32 EntriesCount
    {
        get { return m_Entries.Count; }
    }

    public Pack()
    {
        m_Entries = new List<PackEntry>();
    }

    #region Methods: Abstract
    ...
    #endregion
}

public sealed class PackTypeA : Pack { ... }
public sealed class PackTypeB : Pack { ... }

还有一个PackEntry子类:

public abstract class PackEntry
{
    protected Byte[] m_Data;

    protected PackEntry() { }

    public Byte[] GetData()
    {
        return m_Data;
    }

    public void SetData(Byte[] data)
    {
        m_Data = data;
    }

    #region Methods: Abstract
    ...
    #endregion
}

public sealed class PackEntryTypeA : PackEntry { ... }
public sealed class PackEntryTypeB : PackEntry { ... }

这意味着派生类PackTypeA将使用PackEntryTypeA条目,而PackTypeB将使用PackEntryTypeB等等。 现在......我正在使用我的Pack抽象类,如下面的代码片段所示:

Pack pack = useTypeA ? new PackTypeA() : new PackTypeB();
pack.AbstractMethod1();

if (condition)
    pack.AbstractMethod2();

...

一切都像魅力一样,但在AbstractMethod1() ... AbstractMethodN()内部覆盖了我对条目列表的大量工作。这需要很多像:

for (Int32 i = 0; i < m_Entries.Count; ++i)
{
    PackEntryTypeA entry = (PackEntryTypeA)m_Entries[i];
    ...

它变得单调乏味。所以我尝试了以下方法为我的Pack类实现泛型类型:

public abstract class Pack<T> where T : PackEntry
{
    protected List<T> m_Entries;

    public Int32 EntriesCount
    {
        get { return m_Entries.Count; }
    }

    public Pack()
    {
        m_Entries = new List<T>();
    }

    #region Methods: Abstract
    ...
    #endregion
}

public sealed class PackTypeA : Pack<PackEntryTypeA> { ... }
public sealed class PackTypeB : Pack<PackEntryTypeB> { ... }

哪个更好,更好!但问题是我不能再使用以下代码片段了:

Pack pack = useTypeA ? new PackTypeA() : new PackTypeB();

因为它需要指定泛型类型(我真的可以&#39;)

Pack<PackTypeN>

我想到的最后一个解决方案是将列表移动到派生类,但它不是很优雅。有人可以帮我指点解决方案吗?

1 个答案:

答案 0 :(得分:2)

Pack<PackEntryTypeA>Pack<PackEntryTypeB>是不同的类型,因此,为了能够将它们存储在同一个变量中,它们必须具有相同的基类或接口。

public static void Main()
{
    var pack = 1 == 1 ? (IPack)new PackTypeA() : (IPack)new PackTypeB();
    pack.AbstractMethod1();
    pack = 1 == 2 ? (IPack)new PackTypeA() : (IPack)new PackTypeB();
    pack.AbstractMethod1();
}

public interface IPack { void AbstractMethod1(); }

public abstract class PackEntry { }

public sealed class PackEntryTypeA : PackEntry {}
public sealed class PackEntryTypeB : PackEntry {}

public abstract class Pack<T> : IPack where T : PackEntry
{
    protected List<T> m_Entries = new List<T>();
    public abstract void AbstractMethod1();
}

public sealed class PackTypeA : Pack<PackEntryTypeA> 
{
    public override void AbstractMethod1() 
    { 
        Console.WriteLine(m_Entries.GetType().ToString());
    }
}

public sealed class PackTypeB : Pack<PackEntryTypeB> 
{
    public override void AbstractMethod1() 
    { 
        Console.WriteLine(m_Entries.GetType().ToString());
    }
}

输出:

System.Collections.Generic.List`1[PackEntryTypeA]
System.Collections.Generic.List`1[PackEntryTypeB]