8

私は C# で書かれたいくつかのコードに取り組んでいます。このアプリでは、カスタム コレクションを次のように定義しています。

public class ResultList<T> : IEnumerable<T>
{
  public List<T> Results { get; set; }
  public decimal CenterLatitude { get; set; }
  public decimal CenterLongitude { get; set; }
}

リザルトで使用されるタイプは、3 つのカスタム タイプの 1 つです。カスタム型のそれぞれのプロパティは、単なるプリミティブ型 (int、string、bool、int?、bool?) です。カスタム タイプの 1 つの例を次に示します。

public class ResultItem
{
  public int ID { get; set; }
  public string Name { get; set; }
  public bool? isLegit { get; set; }
}

作成した ResultList オブジェクトのディープ コピーを実行するにはどうすればよいですか。この投稿を見つけました: Generic method to create deep copy of all elements in a collection。しかし、私はそれを行う方法を理解できません。

4

5 に答える 5

16

コーディングの労力が最も少ないアプローチは、BinaryFormatter.

次の拡張メソッドを定義できます ( Kilhoffer の回答から取得):

public static T DeepClone<T>(T obj)
{
    using (var ms = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(ms, obj);
        ms.Position = 0;
        return (T)formatter.Deserialize(ms);
    }
}

…そして、次のように呼び出します。

ResultList<T> clone = DeepClone(original);
于 2012-06-17T20:07:31.570 に答える
9

ResultListクラスがJonSkeetので機能しない理由の1つは、ICloneableインターフェイスを実装していないためです。

クローンを作成する必要があるすべてのクラスにICloneableを実装します。

public class ResultItem : ICloneable
{
  public object Clone()
  {
    var item = new ResultItem
                 {
                   ID = ID,
                   Name = Name,
                   isLegit = isLegit
                 };
    return item;
  }
}

また、ResultListにも:

public class ResultList<T> : IEnumerable<T>, ICloneable where T : ICloneable
{
  public List<T> Results { get; set; }
  public decimal CenterLatitude { get; set; }
  public decimal CenterLongitude { get; set; }

  public object Clone()
  {
    var list = new ResultList<T>
                 {
                   CenterLatitude = CenterLatitude,
                   CenterLongitude = CenterLongitude,
                   Results = Results.Select(x => x.Clone()).Cast<T>().ToList()
                 };
    return list;
  }
}

次に、オブジェクトのディープコピーを作成します。

resultList.clone();
于 2012-06-17T20:51:11.503 に答える
2

ここに私が必要として書いたものがあります。リフレクションを使用してすべてのプロパティ(および指定されている場合はプライベートなもの)をコピーします

public static class ObjectCloner
{
    public static T Clone<T>(object obj, bool deep = false) where T : new()
    {
        if (!(obj is T))
        {
            throw new Exception("Cloning object must match output type");
        }

        return (T)Clone(obj, deep);
    }

    public static object Clone(object obj, bool deep)
    {
        if (obj == null)
        {
            return null;
        }

        Type objType = obj.GetType();

        if (objType.IsPrimitive || objType == typeof(string) || objType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == 0) == null)
        {
            return obj;
        }

        List<PropertyInfo> properties = objType.GetProperties().ToList();
        if (deep)
        {
            properties.AddRange(objType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)); 
        }

        object newObj = Activator.CreateInstance(objType);

        foreach (var prop in properties)
        {
            if (prop.GetSetMethod() != null)
            {
                object propValue = prop.GetValue(obj, null);
                object clone = Clone(propValue, deep);
                prop.SetValue(newObj, clone, null);
            }
        }

        return newObj;
    }
}
于 2014-03-11T14:31:20.893 に答える