user981225
user981225

Reputation: 9252

Implementing a Generic method

I created an interface with one method, the ability to copy the contents of one object into another object of the same type (the actual functionality is irrelevant to the question).

public interface IDeepClonable
{
    void DeepClone<T>(T other);
}

I'm having trouble with a proper implementation.

What I really would like is to implement it like this (where this is inside ClassA, which implements IDeepClonable)

public void DeepClone<ClassA>(ClassA other)
{
    this.A = other.A;
}

However this does not work, as the 'other' object is not recognized as an instance of ClassA by the compiler (why?)

This does not work either, as it gives a 'the constraints for type parameter T must match the (...) interface method.

public void DeepClone<T>(T other) where T : ClassA
{
    this.A= other.A;
}

I can solve all problems by changing the interface to take in an object instead of a generic constraint, but I was hoping for a more elegant solution.

I can also solve this by turning the interface into a generic interface, but then then that forces me to cast to that generic interface.

Upvotes: 4

Views: 3628

Answers (2)

SLaks
SLaks

Reputation: 887433

You're trying to use the CRTP.

You need to write

public interface IDeepClonable<out T> where T : IDeepClonable<T>
{
    void DeepClone(T other);
}

public class ClassA : IDeepClonable<ClassA> {
    void DeepClone(ClassA other) { ... }
}

However, this means that any code that uses IDeepClonable must itself become generic, which will end up becoming unwieldy.

The CLR type system is not rich enough to do what you really want.

Upvotes: 5

user694833
user694833

Reputation:

The problem is that you have declared a generic method in the interface, and you have to implement exactly like that in the derived class:

public class ClassA : IDeepClonable 
{ 
    void DeepClone<T>(T other) { /* some implementation here */ } 
} 

Something different than that won't work.

Said that, why you need this kind of complexity, you don't need the generic here, just implement as:

public interface IDeepClonable 
{ 
    void DeepClone(IDeepClonable other); 
} 

public class ClassA : IDeepClonable 
{ 
    void DeepClone(IDeepClonable other)
    {
         // just to be sure ....
         if (other is ClassA) 
         {
             var o = (ClassA)other;
             this.A = o.A; 
         }
    } 
} 

Upvotes: 0

Related Questions