具有泛型子类型的抽象类

本文关键字:抽象类 类型 泛型 | 更新日期: 2024-10-23 06:06:02

我实现了一个抽象类,如下所示:

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();

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

Pack<PackTypeN>

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

具有泛型子类型的抽象类

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]