2012-05-07 18 views
3

私は、1つのオブジェクトの内容を同じタイプの別のオブジェクトにコピーするという方法でインターフェイスを作成しました(実際の機能は質問とは関係ありません)。一般的なメソッドの実装

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

適切な実装に問題があります。私は本当にたい何

「その他」のオブジェクトは次のように認識されないよう、

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

は、しかし、これは動作しません(これはIDeepClonableを実装にClassA、内側にある場合)は、このようにそれを実装することです(なぜ?)

これは、型パラメータTの制約が(...)インタフェースメソッドと一致しなければならないため、どちらも動作しません。

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

一般的な制約の代わりにオブジェクトを取り込むようにインターフェイスを変更することで、すべての問題を解決できますが、私はより洗練されたソリューションを望んでいました。

これを解決するには、インターフェイスを汎用インターフェイスに変更しますが、そのインターフェイスを汎用インターフェイスにキャストする必要があります。

+0

。 'DeepClone'という名前のメソッドはコピーを返さなければなりません。あなたは 'DeepCloneFrom'かそれに類するものに名前をつけるべきです。 – SLaks

+0

あなたが深いクローン作成をしたいならば、メソッド 'T AsImmutable()'、 'IModifiableClone 'とメソッド 'U AsNewMutable()'を使って 'IImmutableClonable 'を定義し、 'IFullClone 'は上記の両方を継承しています。変更不能なオブジェクトは、単に 'AsImmutable()'実装から自分自身を返すでしょう。 'AsNewMutable()'は、少なくとも 'U'の契約で必要とされる突然変異の方法を許可するものを返します。 – supercat

答えて

5

CRTPを使用しようとしています。あなたは

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

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

を記述する必要が

はしかし、これはIDeepClonableを使用して任意のコード自体が手に負えなくなってしまうであろう、ジェネリックにならなければならないことを意味します。

CLRタイプのシステムは、あなたが本当に必要とするほど豊富ではありません。それよりも異なる

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

何かが動作しません。

+1

ここでCRTPを使用する際の1つの問題は、クローン可能なデリバティブとクローン不可能なデリバティブの両方を含む基本クラスを持ち、クローン可能でないデリバティブがクローン可能なサブデリバティブを持つ可能性があることです。 'T 'に制約を加えることは、その不在時にはできない何かをすることを許しますか?また、 'T'を共変(' out')型のパラメータにしない理由はありますか? – supercat

+0

@supercat:私はそれを考えなかった。 – SLaks

0

問題では、インターフェイスでジェネリックメソッドを宣言している、とあなたは正確に派生クラスでそのように実装する必要があることです。

あなたは複雑のこの種を必要とする理由、あなただけのように実装し、ここでは一般的なを必要としない、と言った: `DeepClone`が間違った名前で、BTW

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; 
     } 
    } 
} 
+0

ありがとうございます。私はこの種の実装を避けることを望んでいました。 – user981225

関連する問題