[英]Create list of generics
I have base class for my entities 我有我的实体的基类
public class Entity<T> where T : Entity<T>, new()
{
public XElement ToXElement()
{
}
public static T FromXElement(XElement x)
{
}
}
I have to use this strange construction Entity<T> where T : Entity<T>
, because i want static method FromXElement to be strongly-typed Also, i have some entities, like that 我必须使用这个奇怪的构造Entity<T> where T : Entity<T>
,因为我希望静态方法FromXElement是强类型的另外,我有一些实体,像那样
public class Category : Entity<Category>
{
}
public class Collection : Entity<Collection>
{
}
How can i create a generic list of my entities, using base class? 如何使用基类创建我的实体的通用列表?
var list = new List<Entity<?>>();
list.Add(new Category());
list.Add(new Collection());
You can't with that definition. 你不能用那个定义。 There is no "common base class" between Category
and Collection
(other than object
, of course). Category
和Collection
之间没有“公共基类”(当然不是object
)。
If there were , say if Entity<T>
were defined as: 如果有 ,如果说Entity<T>
被定义为:
public class Entity
{
}
public class Entity<T> : Entity where T : Entity<T>, new()
{
public XElement ToXElement()
{
}
public static T FromXElement(XElement x)
{
}
}
then you could do 那么你可以做到
var list = new List<Entity>();
list.Add(new Category());
list.Add(new Collection());
But what would that buy you? 但是那会买什么?
Create a marker interface: 创建标记界面:
public interface IAmAGenericEntity { }
public class Entity<T> where T : IAmAGenericEntity, new()
// ...
public class Category : Entity<T>, IAmAGenericEntity
// ....
var list = new List<IAmAGenericEntity>();
// ...
From the lack of an abstract
marker on Entity
, I assume that To
/ FromXElement
use reflection and should work for any subtype of Entity
. 由于缺少Entity
上的abstract
标记,我假设To
/ FromXElement
使用反射并且应该适用于Entity
任何子类型。 I recommend that you structure your classes as follows: 我建议您按如下方式构建类:
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);
}
}
The "boilerplate" is minimal, and it doesn't require that you creatively circumvent the type system. “样板”是最小的,并且它不需要您创造性地绕过类型系统。 You don't have to worry about the lack of a common base, or about manual conversions. 您不必担心缺乏共同基础或手动转换。 If you like, you can eliminate the boilerplate entirely and just construct your objects directly from Entity
: 如果您愿意,可以完全消除样板,只需直接从Entity
构建对象:
public class Entity
{
public XElement ToXElement() { ... }
public static T FromXElement<T>(XElement x)
where T : Entity
{
...
}
}
In essence, what you're doing is implementing a type class, which C# does not directly support. 从本质上讲,你正在做的是实现一个C#不直接支持的类型类。 There are a number of ways to work around this lack, but I usually find them to be more trouble than they're worth, especially when it comes to static methods. 有很多方法可以解决这个缺点,但我经常发现它们比它们的价值更麻烦,特别是在涉及静态方法时。 If C# supported static extension methods, it would be simple, but alas it does not. 如果C#支持静态扩展方法,那将很简单,但它不会。
You can define a non-generic class to be the base class of all entity classes 您可以将非泛型类定义为所有实体类的基类
public class Entity
{
}
and make Entity inherit Entity 并使实体继承实体
public class Entity<T> : Entity where T : Entity<T>, new()
{
}
Now you can create the list of entities as: 现在,您可以创建实体列表:
var list = new List<Entity>();
You can solve this problem by adding a non-generic version of the class 您可以通过添加类的非泛型版本来解决此问题
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> {}
and then create the list of the base class: 然后创建基类列表:
var list = new List<Entity>()
list.Add(new Cathegory());
Then, if you want to call a "generic specific" operation, you need to call the "As" function or simply cast the object. 然后,如果要调用“特定于通用”操作,则需要调用“As”函数或简单地转换对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.