I have the following:
public class InstanceList : List<Instance> {}
I would like to make this cloneable. Following the example here: Why no ICloneable<T>?
I tried the following:
public interface ICloneable<T> : ICloneable Where T : ICloneable<T>
{ new T Clone(); }
public class InstanceList : List<Instance>, ICloneable<List<Instance>> {}
But I get a compiler error. The error message states that
List<Instance>
must be convertible to
ICloneable<List<Instance>>
in order to use parameter T in the generic interface
ICloneable<T>
.
What am I missing here?
You can't do this, because you can't define List<T>
yourself. You would only be able to do this if you could declare your own List<T>
because of the way you've constrained ICloneable<T>
. Since List<T>
truly doesn't implement ICloneable<T>
, you're going to have to have the type of T be InstanceList instead, which you do have control over.
Here's how you would implement it:
public class InstanceList : List<Instance>, ICloneable<InstanceList>
{
public InstanceList Clone()
{
// Implement cloning guts here.
}
object ICloneable.Clone()
{
return ((ICloneable<InstanceList>) this).Clone();
}
}
public class Instance
{
}
public interface ICloneable<T> : ICloneable where T : ICloneable<T>
{
new T Clone();
}
Of course, there is another alternative you could do. You could widen your generics a little bit, to create a CloneableList<T>
type:
public class CloneableList<T> : List<T>, ICloneable<CloneableList<T>>
{
public CloneableList<T> Clone()
{
throw new InvalidOperationException();
}
object ICloneable.Clone()
{
return ((ICloneable<CloneableList<T>>) this).Clone();
}
}
public interface ICloneable<T> : ICloneable where T : ICloneable<T>
{
new T Clone();
}
And if you really want to get fancy, create something that restricts T to ICloneable. Then you could implement ICloneable on the Instance class, and anything else you want to include in an ICloneable<T>
list, thus treating every CloneableList<T>
in the exact same way, avoiding a different implementation of ICloneable<T>
for each and every cloneable list you want to create.
public class CloneableList<T> : List<T>, ICloneable<CloneableList<T>> where T : ICloneable
{
public CloneableList<T> Clone()
{
var result = new CloneableList<T>();
result.AddRange(this.Select(item => (T) item.Clone()));
return result;
}
object ICloneable.Clone()
{
return ((ICloneable<CloneableList<T>>) this).Clone();
}
}
public interface ICloneable<T> : ICloneable where T : ICloneable<T>
{
new T Clone();
}