我的实体有基类
public class Entity<T> where T : Entity<T>, new()
{
public XElement ToXElement()
{
}
public static T FromXElement(XElement x)
{
}
}
我必须使用这个奇怪的构造Entity<T> where T : Entity<T>
,因为我希望静态方法FromXElement是强类型的
此外,我有一些实体,如
public class Category : Entity<Category>
{
}
public class Collection : Entity<Collection>
{
}
如何使用基类创建我的实体的通用列表?
var list = new List<Entity<?>>();
list.Add(new Category());
list.Add(new Collection());
答案 0 :(得分:4)
您不能使用该定义。没有&#34;共同基类&#34;在Category
和Collection
之间(当然不是object
)。
如果 ,请说明Entity<T>
是否定义为:
public class Entity
{
}
public class Entity<T> : Entity where T : Entity<T>, new()
{
public XElement ToXElement()
{
}
public static T FromXElement(XElement x)
{
}
}
然后你可以做
var list = new List<Entity>();
list.Add(new Category());
list.Add(new Collection());
但是那会买什么?
答案 1 :(得分:1)
创建标记界面:
public interface IAmAGenericEntity { }
public class Entity<T> where T : IAmAGenericEntity, new()
// ...
public class Category : Entity<T>, IAmAGenericEntity
// ....
var list = new List<IAmAGenericEntity>();
// ...
答案 2 :(得分:1)
由于abstract
上缺少Entity
标记,我认为To
/ FromXElement
使用反射,并且应该适用于Entity
的任何子类型。我建议您按如下方式构建类:
public class Entity
{
public XElement ToXElement() { ... }
protected static T FromXElement<T>(XElement x)
where T : Entity
{
...
}
}
public class Category : Entity
{
public static Category : FromXElement(XElement x)
{
return FromXElement<Category>(x);
}
}
“样板”是最小的,并且它不需要您创造性地绕过类型系统。您不必担心缺乏共同基础或手动转换。如果您愿意,可以完全删除样板,只需直接从Entity
构建对象:
public class Entity
{
public XElement ToXElement() { ... }
public static T FromXElement<T>(XElement x)
where T : Entity
{
...
}
}
从本质上讲,你所做的是实现一个C#不直接支持的类型类。有很多方法可以解决这个缺点,但我经常发现它们比它们的价值更麻烦,特别是在涉及静态方法时。如果C#支持静态扩展方法,那将很简单,但它不会。
答案 3 :(得分:0)
您可以将非泛型类定义为所有实体类的基类
public class Entity
{
}
并使实体继承实体
public class Entity<T> : Entity where T : Entity<T>, new()
{
}
现在您可以创建实体列表:
var list = new List<Entity>();
答案 4 :(得分:0)
您可以通过添加类的非泛型版本来解决此问题
class Entity
{
// methods
public T As<T>()
{
if (this is T) return (T)this;
throw new InvalidCastException();
}
}
class Entity<T> : Entity where T : Entity<T>, new()
class Cathegory : Entity<T> {}
然后创建基类列表:
var list = new List<Entity>()
list.Add(new Cathegory());
然后,如果要调用“特定于通用”操作,则需要调用“As”函数或简单地转换对象。