クローン可能

# クラスに ICloneable を実装する

ICloneable を実装する ひねりのあるクラスで。 public タイプセーフ Clone() を公開する object Clone() を実装します

public class Person : ICloneable
{
    // Contents of class
    public string Name { get; set; }
    public int Age { get; set; }
    // Constructor
    public Person(string name, int age)
    {
        this.Name=name;
        this.Age=age;
    }
    // Copy Constructor
    public Person(Person other)
    {
        this.Name=other.Name;
        this.Age=other.Age;
    }

    #region ICloneable Members
    // Type safe Clone
    public Person Clone() { return new Person(this); }
    // ICloneable implementation
    object ICloneable.Clone()
    {
        return Clone();
    }
    #endregion
}

後で次のように使用されます:

{
    Person bob=new Person("Bob", 25);
    Person bob_clone=bob.Clone();
    Debug.Assert(bob_clone.Name==bob.Name);

    bob.Age=56;
    Debug.Assert(bob.Age!=bob.Age);
}

bob の年齢を変更することに注意してください bob_clone の年齢を変更しません .これは、設計が (参照) 変数の代入ではなく複製を使用しているためです。

# 構造体に ICloneable を実装する

構造体は代入演算子 = を使用してメンバーごとのコピーを行うため、構造体の ICloneable の実装は通常必要ありません。 .ただし、設計上、ICloneable から継承する別のインターフェイスの実装が必要になる場合があります。 .

もう 1 つの理由は、構造体にコピーが必要な参照型 (または配列) が含まれている場合です。

// Structs are recommended to be immutable objects
[ImmutableObject(true)]
public struct Person : ICloneable
{
    // Contents of class
    public string Name { get; private set; }
    public int Age { get; private set; }
    // Constructor
    public Person(string name, int age)
    {
        this.Name=name;
        this.Age=age;
    }
    // Copy Constructor
    public Person(Person other)
    {
        // The assignment operator copies all members
        this=other;
    }

    #region ICloneable Members
    // Type safe Clone
    public Person Clone() { return new Person(this); }
    // ICloneable implementation
    object ICloneable.Clone()
    {
        return Clone();
    }
    #endregion
}

後で次のように使用されます:

static void Main(string[] args)
{
    Person bob=new Person("Bob", 25);
    Person bob_clone=bob.Clone();
    Debug.Assert(bob_clone.Name==bob.Name);
}

# 構文

  • オブジェクト ICloneable.Clone() { return Clone(); } // カスタム public Clone() 関数を使用するインターフェイス メソッドのプライベート実装。
  • public Foo Clone() { return new Foo(this); } // public clone メソッドはコピー コンストラクタ ロジックを利用する必要があります。

# コメント

CLR メソッド定義 object Clone() が必要です これは型安全ではありません。この動作をオーバーライドし、含まれているクラスのコピーを返すタイプ セーフなメソッドを定義するのが一般的な方法です。

クローン作成が浅いコピーのみを意味するのか、ディープ コピーのみを意味するのかを決定するのは作成者次第です。参照を含む不変の構造については、ディープ コピーを行うことをお勧めします。クラス自体が参照であるため、浅いコピーを実装することはおそらく問題ありません。

注:C# で インターフェイス メソッドは、上記の構文でプライベートに実装できます。