具有通用子类型的摘要 Class

Abstract Class with Generic Subtype

我实现了如下抽象 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 subclass 还有:

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 { ... }

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

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 class:

实现泛型类型
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();

因为它需要指定泛型类型(我真的不能):

Pack<PackTypeN>

我想出的最后一个解决方案是将列表移至派生的 classes,但这不是很优雅。有人可以给我指出解决方案吗?

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

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]