3

我有两个对象序列“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>泛型看起来像它初始化的对象,并且由于我不能从与类型参数相同的类型继承,所以它不适合我的初始目的。

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

4

2 回答 2

3

这间接地是您试图在上面的代码中声明的内容。

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

这有意义吗?

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

于 2013-02-28T21:58:12.910 回答
1

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

你真的不需要花哨的泛型。有什么问题:

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

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

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

于 2013-02-28T22:27:02.313 回答