.Net泛型 - 从接口实现继承

时间:2013-02-28 21:51:05

标签: c# generics inheritance interface

我有两个对象序列'A'和'B'。比较序列应产生第三个序列'C',表示是否:

  • 对象从“A”或
  • “删除”
  • 从'B'“插入”。

所有剩余的元素都被视为“匹配”。

我想做什么:

声明从Inserted<T>基类继承其所有属性的Deleted<T>Matched<T>T泛型类。泛型类必须能够从它继承的对象中实例化自己。

代码:

public interface IInstantiable<T>
{
    void CopyFrom(T o);
}

[Serializable]
public class Inserted<T> : T
    where T : IInstantiable<T>
{
    public Inserted() { }
    public Inserted(T t)
    {
        this.CopyFrom(t);
    }
}

错误:

'MyNamespace.Inserted<T>' does not contain a definition for 'CopyFrom' and no 
extension method 'CopyFrom' accepting a first argument of type 'MyNamespace.Inserted<T>' 
could be found (are you missing a using directive or an assembly reference?)

进一步讨论:

我定义了自己的IInstantiable接口来强制存在CopyFrom方法。我不能使用标准ICloneable接口,因为它只定义了一个将对象复制到新实例的方法,而我需要该对象在构造函数中复制其成员。

如果泛型定义了自己的CopyFrom方法实现,则错误消失;但是,这并没有达到专门化CopyFrom方法来处理基类特定需求的目标。只有基类才能知道应该复制哪些属性。 (或者我错过了什么?)

注意:最终对象应该具有与其基类相同的公共成员,因为该对象应该能够序列化。

这在.NET中是否可行?

答案:

我试图做的事情是不可能的,因为泛型类不能是模板基类的扩展。 Visual Studio抱怨“无法从'T'派生,因为它是一个类型参数。” (我还没有注意到这个错误,因为我还没有在泛型类中实现CopyFrom方法。)

如果我要将接口更改为类并在该类中提供存根实现,我可以继承它,如下所示;但是,这会在我的继承层次结构中引入一个新的基类。

public class IInstantiable<T>
{
    public virtual void CopyFrom(T o) { }
}

[Serializable]
public class Inserted<T> : IInstantiable<T>
    where T : IInstantiable<T>
{
    public Inserted() { }
    public Inserted(T t)
    {
        base.CopyFrom(t);
    }
}

不幸的是,我不能在它的模板化形式中使用这个新的基类,因为我必须在我的继承层次结构的根目录中引入它。它仅在我删除模板并使其尽可能通用时才有效。

public class IInstantiable
{
    public virtual void CopyFrom(Object o) { }
}

但是,这仍然不会使我的Inserted<T>泛型看起来像它初始化的对象,并且因为我不能从类型参数继承相同的类型,所以它不适合我的初始目的。

从基于类型系统的“花式仿制药”转向更多(ahem)通用注释结构可能被证明是最佳解决方案;但是,我选择的序列化方法(XmlSerialization)的默认行为没有自动支持,这将使此配置成为可行的解决方案。泛型不起作用;改为使用硬编码的类定义。

2 个答案:

答案 0 :(得分:3)

这是您在上面的代码中尝试声明的内容。

[Serializable]
public class Inserted<T> : IInstantiable<T>
    where T : IInstantiable<T>
{
    public Inserted() { }
    public Inserted(T t)
    {
        this.CopyFrom(t);
    }
}

这有意义吗?

.NET不允许您从泛型参数继承。怎么可能呢?泛型在运行时进行评估,但它需要知道您的类在编译时的类型。

答案 1 :(得分:1)

如果我理解正确,你想用一个对象序列注释它们的状态(插入,删除或匹配)的概念。

你真的不需要花哨的仿制品;怎么了:

enum ChangeState { Inserted, Deleted, Matched }
struct<T> Annotated { 
    public T Obj; 
    public ChangeState;
}

您可以根据需要将其标记为序列化(Annotated对象可以在没有相同属性/字段的情况下进行序列化。)

虽然您可以在类型系统中编码更多信息,但我不清楚这里的好处是什么。你确定要这么做吗?