Реализация интерфейса ICloneable C # (глубокое клонирование) - PullRequest
2 голосов
/ 09 ноября 2009

Я искал код, который реализовал интерфейс ICloneable для одного из классов.

Класс был следующим:

public class TempClass
{
  String[] names;
  String[] values;
}

Был создан частичный класс, который реализовал TempClass

public partial class TempClass:ICloneable
{
   public Object Clone()
   {
      TempClass cloneClass = new TempClass();
      String[] cloneNames = new String[this.names.Length - 1];
      String[] cloneValues = new String[this.values.Length -1];

      Array.Copy(this.names,cloneNames,this.names.Length);
      Array.Copy(this.values,cloneValues,this.values.Length);

      cloneClass.names = cloneNames;
      cloneValues.values = cloneValues;

      return cloneClass;

   }

}

Мне было интересно, будет ли это правильным способом сделать глубокую копию объекта? Флаги здесь вызывают промежуточные структуры cloneNames и cloneValues, которые используются для копирования значений исходного объекта и имеют переменные-члены Names и Values, указывающие на него, а затем возвращают ссылку на объект, созданную в методе clone.

Любые отзывы по этому фрагменту будут высоко оценены

Спасибо

Ответы [ 3 ]

4 голосов
/ 09 ноября 2009

Ну, есть одна проблема - вы не создаете новые строковые массивы нужного размера. Должно быть:

String[] cloneNames = new String[this.names.Length];
String[] cloneValues = new String[this.values.Length];

Или как простое решение:

String[] cloneNames = (String[]) this.names.Clone();
String[] cloneValues = (String[]) this.values.Clone();

Кроме этого, все должно быть в порядке. Не могли бы вы объяснить свою проблему более подробно?

2 голосов
/ 09 ноября 2009

Array.Clone и Array.Copy оба создают неглубокие копии (как описано в связанной документации API), но при использовании строковых массивов возникает проблема, поскольку строки неизменяемы .СЕТЬ. Когда вы делаете это:

stringArray[0] = "first value";
stringArray[0] = "second value";

Первый экземпляр строки заменяется другим, так что похоже, что вы сделали глубокую копию (а для строковых массивов вы могли бы сделать именно это).

Чтобы выполнить глубокое копирование объекта с массивами обычных ссылочных типов, вам необходимо создать новые экземпляры элементов массива. Скажем, TempClass хранит массив Cookie объектов вместо строк:

public Object Clone() {
    TempClass clone = new TempClass();

    clone.cookieArray = new Cookie[this.cookieArray.Length];
    for(int i = 0; i < this.cookieArray.Length; i++) {
        Cookie cookie  = this.cookieArray[i];
        clone.cookieArray[i] = new Cookie(cookie.Name, cookie.Value, cookie.Path, cookie.Domain);
    }
}
0 голосов
/ 09 ноября 2009

Вы можете переписать свой метод клонирования следующим образом, в противном случае пони прав.

public Object Clone()
{
    return new TempClass
    {
        names = this.names == null? null:this.names.ToArray(),
        values = this.values == null? null:this.values.ToArray()
    };
}

Может быть немного медленнее, чем клон, но работает.

...