简体   繁体   English

创建泛型列表

[英]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). CategoryCollection之间没有“公共基类”(当然不是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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM