5

我的实体有基类

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());
4

5 回答 5

4

你不能用那个定义。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());

但这会给你带来什么?

于 2012-10-10T19:40:58.710 回答
1

创建标记界面:

public interface IAmAGenericEntity { }

public class Entity<T> where T : IAmAGenericEntity, new()
// ...

public class Category : Entity<T>, IAmAGenericEntity
// ....

var list = new List<IAmAGenericEntity>();
// ...
于 2012-10-10T19:44:54.717 回答
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# 支持静态扩展方法,那会很简单,可惜它不支持。

于 2012-10-10T19:59:07.250 回答
0

您可以定义一个非泛型类作为所有实体类的基类

public class Entity
{
}

并使实体继承实体

public class Entity<T> : Entity where T : Entity<T>, new()
{
}

现在您可以将实体列表创建为:

var list = new List<Entity>();
于 2012-10-10T19:44:40.830 回答
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”函数或简单地转换对象。

于 2012-10-10T19:44:42.153 回答