我遇到与this post中的问题类似的问题。
我还在网上看到成千上万的帖子,说你可以把任何扩展特定基类的泛型类放到基类类型的集合中。我完全理解这一点。
我的问题与上面的链接帖和其他基本方式不同 - 我的泛型类有一个通用的基类。更糟糕的是,这是一个非常大的MVVM应用程序框架(内部构建)的一部分,通用基类也有一个基类等等......每个基类都添加了某些属性和功能,它看起来有点像这样:
DataListEntry< T> < -BaseSynchronisableDataType< T> < - BaseAuditDataType< - BaseDataType< - BaseAnimatableDataType
应用程序集合类使用类似的继承:
的DataList< T> < -BaseSynchronisableCollection< T> < - BaseAnimatableCollection< T> < -BaseCollection< T> < - SortableObservableCollection< T>
更糟糕的是,每个通用声明都有约束,例如,BaseSynchronisableDataType< T>的定义。看起来像这样:
public abstract class BaseSynchronisableDataType<T> : BaseAuditDataType,
ISynchronisable<T>, ICloneable<T>, IEquatable<T> where T : class, ICloneable<T>,
IEquatable<T>, new()
因此,每个泛型集合类型都通过这些约束绑定到泛型基类。希望到现在为止,您可以看到我的问题的规模。
我尝试使用接口(上面没有显示)来删除从集合到各自基类的链接,但由于相关类的一些通用约束,这也失败了。例如,我无法创建接口类型的集合,因为在某些基类上存在必要的通用“类”约束,因此我得到错误,指出集合的类型'必须是非抽象类型,一个公共无参数构造函数,以便在泛型类型或方法'。
中将其用作参数'T'最后一点需要注意的是我正在尝试做什么:
我需要使用不同的类来填充集合,这些类都扩展了DataList&lt; T&gt;。基类。这些类仅在名称上有所不同,并且在它们中具有完全相同的属性。它们声明如下:
public class Writer : DataListEntry<Writer>
public class Artist : DataListEntry<Artist>etc.
如果您有任何想法,请告诉我...我已经在这个问题上遭受了2天的痛苦而我的老板也不高兴!非常感谢Sheridan。
答案 0 :(得分:7)
这里有一个关键原则,您需要了解 - 即使Foo<Child>
是Foo<Parent>
的子类,类Child
也不是Parent
的子类1}} 的。这意味着List<Foo<Parent>>
不能包含List<Foo<Child>>
的实例,只能包含字符串或Int32。
要理解为什么会出现这种情况,想象下面的代码(不编译,但说明了为什么上述语句必须为真):
var myIntList = new List<Int>();
var myObjectList = (List<Object>)myIntList;
// Uh oh, now I can add a string to a list of integers...
myObjectList.Add("Foo");
您对curiously recurring template pattern的使用消除了所有类之间的继承层次结构。因为它们不再共享基类,所以不能将它们放入比List<Object>
更具体的列表中
在您的情况下,最好的方法可能是创建一个DataListEntry实现的非泛型接口,并创建该接口的列表。如果界面提供了该类型实例中所需的所有成员,那么您已经完成了设置。
例如:
public interface IDataListEntry {
bool QuacksLikeADuck { get; }
bool WalksLikeADuck { get; }
}
public abstract class DataListEntry<T> : IDataListEntry where ... {
// Implement these in subclasses
abstract bool QuacksLikeADuck { get; }
abstract bool WalksLikeADuck { get; }
}
然后你可以:
List<IDataListEntry> myDataListEntries = new List<IDataListEntry>();
myDataListEntries.Add(new Writer(...));
myDataListEntries.Add(new Artist(...));
IEnumerable ducks = myDataListEntries.Where(dle => dle.WalksLikeADuck && dle.QuacksLikeADuck);
或者(可能更适合您的情况),如果您需要知道T
特定实例中IDataListEntry
的类型:
public interface IDataListEntry {
Type TheTypeOfT { get; }
}
public class DataListEntry<T> : IDataListEntry where ... {
Type TheTypeOfT { get { return typeof(T); } }
}
然后执行:
List<IDataListEntry> myDataListEntries = new List<IDataListEntry>();
myDataListEntries.Add(new Writer(...));
myDataListEntries.Add(new Artist(...));
IEnumerable artists = myDataListEntries.Where(dle => typeof(Artist).IsAssignableFrom(dle.TheTypeOfT));
答案 1 :(得分:0)
我会一直回到基础,并使用一些简单的linq来获取类筛选列表。
声明类型对象DataList<object> L
的列表,然后当您被要求输入类型时,请调用L.OfType<Type>()
来过滤列表。对象将是你可以使用的最通用的东西。你可能能够使用所有扩展的基类型,但因为它的摘要我不知道你是否可以声明该类型的列表。
在我自己的代码中,我使用泛型约束来实现类似的东西。
public abstract class BusinessObjectBase : //some interfaces
{
//class stuff and events
}
我有一堆delcared的对象扩展了我的基类,现在我可以做到这一点
Collection<BusinessObjectBase> temp = new Collection<BusinessObjectBase>();
temp.Add(new RXEvents());
temp.Add(new RXBattery());
temp.Add(new RXBHA());
其中每个添加到列表中的类都是通过扩展BusinessObjectBase来创建的。您正在尝试非常相似的东西,但您的基本实现是不同的。通过将基本类型本身声明为模板化,您将打破基本类型。 Base与Note相同,除了object之外,两者不会实现任何共同点。
Base<>
与Base<X>
或Base<Y>
无关。现在,如果你像这样贬低它
public abstract class BaseSynchronisableDataType<T> : BaseAuditDataType, ISynchronisable<T>, ICloneable<T>, IEquatable<T> where T : MyCustomBaseClass, ICloneable<T>, IEquatable<T>, new()
然后,您可以使用MyCustomBaseClass
作为列表类型,因为您可以保证<T>
代表的所有对象都是其子对象。这似乎打败了创建BaseSynchronisableDataType的目的......
答案 2 :(得分:0)
好的,问题是我无法声明以下内容
DataList<Artist> artists = new DataList<Artist>();
当BaseDataListEntry
类由于BaseSynchronisableCollection<T>
扩展的通用DataList<T>
类的通用约束而不是通用的时。它必须T
属于BaseSynchronisableDataType<T>
类无法扩展的类型BaseDataListEntry
,因为它不是通用的。我需要BaseDataListEntry
类不是通用的,以便我可以将DataList<T>
的所有不同集合放入视图模型中的DataList<BaseDataListEntry>
集合中(一次一个取决于用户的选择)。
解决方案是创建一个IBaseSynchronisableDataType<T>
接口,并在通用约束中使用它而不是具体的BaseSynchronisableDataType<T>
类。然后,我在BaseDataListEntry
类中实现了它,所以现在满足所有约束。不知道为什么我之前没有看到它。
谢谢你所有的时间。