She*_*dan 1 c# generics collections base-class
我在这篇文章中遇到了类似的问题.
我还在网上看到成千上万的帖子,说你可以把任何扩展特定基类的泛型类放到基类类型的集合中.我完全理解这一点.
我的问题不同于上面的链接帖和其他基本方式 - 我的泛型类有一个通用的基类.更糟糕的是,这是一个非常大的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()
Run Code Online (Sandbox Code Playgroud)
因此,每个泛型集合类型都通过这些约束绑定到泛型基类.希望到现在为止,您可以看到我的问题的规模.
我已经尝试使用接口(上面没有显示)来删除从集合到其各自基类的链接,但由于相关类的一些通用约束,这也失败了.例如,我无法创建接口类型的集合,因为在某些基类上存在必要的通用"类"约束,因此我得到错误,指出集合的类型'必须是非抽象类型,公共无参数构造函数,以便在泛型类型或方法中将其用作参数'T'.
最后一点需要注意的是我正在尝试做的事情:
我需要使用不同的类填充集合,这些类都扩展了DataList <T>基类.这些类仅在名称上有所不同,并且具有完全相同的属性.它们声明如下:
public class Writer : DataListEntry<Writer>
public class Artist : DataListEntry<Artist>etc.
Run Code Online (Sandbox Code Playgroud)
如果您有任何想法,请告诉我...我已经在这个问题上遭受了2天的痛苦而我的老板也不高兴!非常感谢Sheridan.
这里有一个关键的原则,你需要理解Foo<Child>- Foo<Parent> 即使Child是一个类的子类,Parent类也不是它的子类.这意味着a List<Foo<Parent>>不能包含List<Foo<Child>>任何可包含字符串或Int32的实例.
要理解为什么会出现这种情况,请设想以下代码(不编译,但说明为什么上述语句必须为true):
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");
Run Code Online (Sandbox Code Playgroud)
使用奇怪的重复模板模式消除了所有类之间的继承层次结构.因为它们不再共享基类,所以不能将它们放入更具体的列表中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; }
}
Run Code Online (Sandbox Code Playgroud)
然后你可以:
List<IDataListEntry> myDataListEntries = new List<IDataListEntry>();
myDataListEntries.Add(new Writer(...));
myDataListEntries.Add(new Artist(...));
IEnumerable ducks = myDataListEntries.Where(dle => dle.WalksLikeADuck && dle.QuacksLikeADuck);
Run Code Online (Sandbox Code Playgroud)
或者(可能更适合您的情况),如果您需要知道T特定实例中的类型IDataListEntry:
public interface IDataListEntry {
Type TheTypeOfT { get; }
}
public class DataListEntry<T> : IDataListEntry where ... {
Type TheTypeOfT { get { return typeof(T); } }
}
Run Code Online (Sandbox Code Playgroud)
然后做:
List<IDataListEntry> myDataListEntries = new List<IDataListEntry>();
myDataListEntries.Add(new Writer(...));
myDataListEntries.Add(new Artist(...));
IEnumerable artists = myDataListEntries.Where(dle => typeof(Artist).IsAssignableFrom(dle.TheTypeOfT));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4286 次 |
| 最近记录: |