0

実装することはお勧めできないことを知ったのでICloneable( Deep Copy と Shallow Copy を区別しないため)、抽象として実装するかインターフェイスとして実装するかを決定しようとしています。

私の実装は、バイナリのディープ コピーMemberwiseCloneシャロー コピーなど、ほぼ同じままであると感じているため、そのためには抽象メソッドが理想的であると感じました。ただし、私の理解では、C# は複数の継承を行わないため、別の抽象クラスを使用する必要がある場合は、もう使用できません。

その場合、カスタムICloneable(例: ICustomCloneable) を実装する方が良いと思いますが、実装が多くのクラスで実質的に同じである場合、コードの再利用を十分に活用していないように感じます。

そうは言っても、インターフェイスを使用して、複製可能なクラスでより重要なことのために抽象継承を明確に保つことは有効ですか? または、これを行う別の方法はありますか?

あるいは、アブストラクトが別のアブストラクトを実装することは有効ですか (読む: 臭くありません)? これは、CloneCapable クラスと別の抽象クラスの実装を妨げる単一継承を回避するための私の推測ですが、疑わしいように思えます。例えば:

public abstract class CloneCapable
{
  public object ShallowCopy()
  {
    // implementation
  }

  public object DeepCopy()
  {
    // implementation
  }
}

public abstract class ClassA : CloneCapable {}

// abstract-abstract since I can't do ClassB : ClassA, CloneCapable
public abstract class ClassB : ClassA {} 
4

2 に答える 2

0

インターフェースを作るのが先だと思っていたのですが、この疑問と最初の答えを見つけました。これはクローンを作成するための優れた方法ですが、カスタム拡張メソッドを使用すると非常にうまくいく可能性があると考えたので、最初の投稿のコードと MS ヘルプ ページに基づいて次のコードを作成しました。

遊ぶいくつかのクラス:

[Serializable]
public abstract class Base
{
    public abstract int m1();
}

[Serializable]
public class derived : Base
{
    public int a = 42;
    public override int m1()
    {
        throw new NotImplementedException();
    }
}

両方のリンクからのコード サンプルに基づく拡張メソッドを持つクラス

//Extension methods must be defined in a static class 
public static class StringExtension
{
    // This is the extension method. 
    // The first parameter takes the "this" modifier
    // and specifies the type for which the method is defined. 
    public static T MyCloneExtension<T>(this T t)
    {
        // Code in this function was copied from https://stackoverflow.com/questions/78536/deep-cloning-objects-in-c-sharp
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", "source");
        }

        // Don't serialize a null object, simply return the default for that object
        if (Object.ReferenceEquals(t, null))
        {
            return default(T);
        }

        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream)
        {
            formatter.Serialize(stream, t);
            stream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(stream);
        }
    }
}

最後にオブジェクトのクローンを呼び出す

derived d = new derived();
derived d2 = d.MyCloneExtension<derived>();
于 2013-08-05T20:34:49.050 に答える