3

I understand the difference between a deep and shallow clone of an object, but according to Simon's answer on this (copy-constructor-versus-clone) question, a generic and non-generic version should be supplied. Why?

You can define two interfaces, one with a generic parameter to support strongly typed cloning and one without to keep the weakly typed cloning ability for when you are working with collections of different types of cloneable objects:

I mean it's trivial enough to make the different interfaces, but in the generic-heavy paradigm of modern C#, I am finding it difficult to come up with a valid reason why you would ever want to use the non-generic and weakly-typed version. Heck, you can even have T:object and do the same thing!

I would write my interfaces like this:

public interface IShallowCloneable { object Clone(); } public interface IShallowCloneable<T> // Should this derive IShallowCloneable? { T Clone(); } public interface IDeepCloneable { object Clone(); } public interface IDeepCloneable<T> // Should this derive IDeepCloneable? { T Clone(); } 

And my class would implement it like this:

public class FooClass : IDeepCloneable<FooClass> { // Implementation } 
1
  • You could also consider making the template interface covariant on the type: see: msdn.microsoft.com/en-us/library/dd997386.aspx. Therefore you need to marke the template argument as out T like IShallowCloneable<out T> Commented Jun 26, 2014 at 9:22

2 Answers 2

5

As that quote says, if you want to be able to work with collections of generic types produced from the same generic definition with different type parameters you really have to provide a non-generic interface.

Consider a list of IDeepCloneable<Widget> and IDeepCloneable<Gadget> instances. You can always make it a List<object>, but then you can't clone them unless you resort to runtime type checks.

If you want to be able to clone (or in general, access in some other manner) these items polymorphically you need them to be typed such that their static type offers the minimum public interface that will let you do the job. In this case, that would make our list a List<IDeepCloneable>.

If you don't intend to use these interfaces polymorphically then having a non-generic IDeepCloneable doesn't offer anything.

Sign up to request clarification or add additional context in comments.

1 Comment

Oh! Now I see, so you'd use the non-generic version when you want to mix different fundamental types together... which is what interfaces were designed to do, ha.
1

You answered your own question. :)

You need the non-generic version for working with non generic collections.

Take for example the IEnumerable and IEnumerable<T> interfaces. The generic interface implements the non-generic one, but only to provide backwards compatibility with non-generic collections:

Ideally all of the generic collection interfaces (e.g. ICollection<T>, IList<T>) would inherit from their non-generic counterparts, such that the generic interface instances could be used with both generic and non-generic code. For example, it would be convenient if an IList<T> could be passed to code that expects an IList.

1 Comment

Thanks for the suggested edits @Kyle. I can't review them because I don't have enough points, so I made the changes manually.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.