I have two sequences of objects 'A' and 'B'. Comparing the sequences should produce a third sequence 'C' of elements that indicate whether:
- the objects were "deleted" from 'A' or
- "inserted" from 'B'.
All remaining elements are considered as "matched".
What I would like to do:
Declare Inserted<T>, Deleted<T>, and Matched<T> generic classes that inherit all their properties from the T base class. The generic class must be able to instantiate itself from the object it inherits.
The code:
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);
}
}
The error:
'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?)
Further discussion:
I define my own IInstantiable interface to enforce the existence of a CopyFrom method. I cannot use the standard ICloneable interface, because it only defines a method that copies the object to a new instance, whereas I need the object to copy its members in the constructor.
The error goes away if the generic defines its own implementation of the CopyFrom method; however, this does not achieve the desired goal of specializing the CopyFrom method to handle the specific needs of the base class. Only the base class could know what properties should be copied. (Or am I missing something?)
Note: The final object should have the same public members as its base class, as the object should be capable of serialization.
Is this possible in .NET?
The answer:
What I am attempting to do is impossible, simply because the generic class cannot be an extension of the template base class. Visual Studio complains "Cannot derive from 'T' because it is a type parameter." (I hadn't noticed this error yet because I had not implemented the CopyFrom method in the generic class yet.)
If I were to change the interface into a class and supply a stub implementation in that class, I could inherit from it as suggested below; however, this introduces a new base class into my inheritance hierarchy.
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);
}
}
Unfortunately, I cannot use this new base class in its templatized form because I must introduce it at the root of my inheritance hierarchy. It works only if I remove the template and make it as generic as possible.
public class IInstantiable
{
public virtual void CopyFrom(Object o) { }
}
However, this still does not make my Inserted<T> generic look like the object it is initialized from, and since I cannot inherit from the same type as the type parameter, it does not suit my initial purpose.
Moving away from "fancy generics" based on the type system to more (ahem) generic annotated structures might prove to be the best solution; however, the default behavior of my selected serialization approach (XmlSerialization) does not have the automatic support that would make this configuration a viable solution. Generics will not work; use hard-coded class definitions instead.
Inserted<T> : Tisn't allowed.public class Inserted<T> : IInstantiable<T>. Does that not work for you?IInstantiable<T>, you just created a templated type based on it. Have you triedpublic class Inserted<T> : IInstantiable<T> : where T IInstantiable<T>? (actually since you didn't template the where wouldn't compile so leave that off)