初学者的问题:如何实现通用列表List<Item>
返回具有名为Data的属性的项目,但为不同的子类返回不同的类型?我开始构建以下层次结构,但这不会导致目标。
abstract class Item
abstract class ItemGeneric<TData> : Item
class ItemText : ItemGeneric<string>
class ItemImage : ItemGeneric<Image>
我创建了一堆ItemText和ItemImage类的实例,并将它们添加到通用List<Item>
列表中。但是,一旦我浏览了列表并希望检索Data属性,就无法访问它(显然)它只在ItemGeneric<TData>
类层次结构级别而不是在Item类中实现。
我想在不使用System.Object
来避免强制转换的情况下解决此问题。
有没有解决这个问题的常见模式?
答案 0 :(得分:1)
如果我理解这个问题,我不能100%确定。
我通常使用带有无类型属性的接口:
interface IUntypedItem
{
object UntypedData {get; }
}
interface IItem<T> : IUntypedItem
{
T Data {get; set;}
}
class abstract ItemGeneric<T> : IItem<T>
{
T Data { get; set; }
object UntypedData { get { return Data; }}
}
class ItemText : ItemGeneric<string>
{
}
然后你可以拥有UntypedItems
的列表List<IUntypedItem> list;
foreach (IUntypedItem item in list)
{
// use item.UntypedData
// or downcast to use typed property
}
如果要在同一列表中处理不同类型,则无法避免转换或对象。你可以说明你在做什么。
答案 1 :(得分:1)
如果您对包含类之外的类型数据执行某些功能,那么您需要预先知道该类型。
不太好:
foreach (Item item in list)
{
ItemGeneric<int> intItem = item as ItemGeneric<int>;
if (intItem != null)
{
//do stuff
}
}
您可以通过将功能移动到包含数据的类中来解决此问题。
所以,您可以像这样使用您的列表:
foreach (Item item in list)
{
item.DoStuff();
}
这意味着您需要在Item类上使用DoStuff:
public abstract class Item
{
public abstract void DoStuff();
}
..并且可以在ItemGeneric上实现它:
public class ItemGeneric<T> : Item
{
public T Data { get; set; }
public override void DoStuff()
{
//do generic typed stuff here
Console.WriteLine(Data);
}
}
答案 2 :(得分:0)
这样的东西?
public class ItemGeneric<T> {
private List<T> data;
}
public class ItemText : ItemGeneric<String> { ... }
public class ItemImage : ItemGeneric<Image> { ... }
在Java中你可以将超类定义为泛型类型T,我不知道它在C#中是如何工作的
public class ItemGeneric<T extends IData> {
private List<T> data;
}
答案 3 :(得分:0)
这是你在BaseClass中创建一个函数的方法,当从derivedclass类型的对象调用时返回DerivedTypes的集合,没有魔法只是泛型。这个例子讨论了HashSet,在你的情况下它可以是你想要的任何类型。
//**The BaseClass**
public class BaseClass<T>
where T : BaseClass<T>
{
public HashSet<T> GetHashSet()
{
HashSet<T> hSet = new HashSet<T>();
//create a HashSet<T>
//do some work
//and return;
return hSet;
}
}
//**The Derived Class**
public class DerivedClass : BaseClass<DerivedClass>
{
//you have the method inherited.
}