Reputation: 23685
I implemented an abstract class like the following:
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 { ... }
And a PackEntry
subclass also:
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 { ... }
This means that the derived class PackTypeA
will use PackEntryTypeA
entries and PackTypeB
will use PackEntryTypeB
and so on.
Now... I'm using my Pack
abstract class as in the following code snippet:
Pack pack = useTypeA ? new PackTypeA() : new PackTypeB();
pack.AbstractMethod1();
if (condition)
pack.AbstractMethod2();
...
Everything works like a charm but inside AbstractMethod1()
... AbstractMethodN()
overrides I'm working a lot with the entries list. Which needs a lot of casting like:
for (Int32 i = 0; i < m_Entries.Count; ++i)
{
PackEntryTypeA entry = (PackEntryTypeA)m_Entries[i];
...
It's getting tedious. So I tried the following approach implementing a generic type to my 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> { ... }
Which is much, much, much better! But the problem is that I can't use the following code snippet anymore:
Pack pack = useTypeA ? new PackTypeA() : new PackTypeB();
Because it requires the generic type to be specified (which I really can't):
Pack<PackTypeN>
The last solution I figured out is to move the list to the derived classes but it's not very elegant. Can someone kindly point me to a solution please?
Upvotes: 0
Views: 174
Reputation: 2108
Pack<PackEntryTypeA>
and Pack<PackEntryTypeB>
are different types, so, to be able to store them in a same variable they have to have same base class or interface.
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());
}
}
Output:
System.Collections.Generic.List`1[PackEntryTypeA]
System.Collections.Generic.List`1[PackEntryTypeB]
Upvotes: 2