Что лучшим способом является к копии клона / глубокой копии.NET универсальный Словарь <строка, T>?

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

190
задан Jon Skeet 15 April 2019 в 03:54
поделиться

5 ответов

Хорошо.NET 2,0 ответа:

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

, Если Вы делаете потребность клонировать значения, можно использовать что-то вроде этого:

public static Dictionary<TKey, TValue> CloneDictionaryCloningValues<TKey, TValue>
   (Dictionary<TKey, TValue> original) where TValue : ICloneable
{
    Dictionary<TKey, TValue> ret = new Dictionary<TKey, TValue>(original.Count,
                                                            original.Comparer);
    foreach (KeyValuePair<TKey, TValue> entry in original)
    {
        ret.Add(entry.Key, (TValue) entry.Value.Clone());
    }
    return ret;
}

, Который полагается TValue.Clone() являющийся соответственно глубоким клоном также, конечно.

174
ответ дан Jon Skeet 23 November 2019 в 05:35
поделиться

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

, Как глубоко Вы хотите, чтобы копия была, и какую версию.NET Вы используете? Я подозреваю, что LINQ, вызов к ToDictionary, определяя и ключ и селектор элемента, будет самым легким способом пойти при использовании.NET 3.5.

, Например, если Вы не возражаете против значения, являющегося мелким клоном:

var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
                                               entry => entry.Value);

, Если Вы уже вынудили T реализовывать ICloneable:

var newDictionary = oldDictionary.ToDictionary(entry => entry.Key, 
                                               entry => (T) entry.Value.Clone());

(Те не тестируются, но должны работать.)

196
ответ дан genesis 23 November 2019 в 05:35
поделиться

Для.NET 2.0 Вы могли реализовать класс, который наследовался от Dictionary и реализует ICloneable.

public class CloneableDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TValue : ICloneable
{
    public IDictionary<TKey, TValue> Clone()
    {
        CloneableDictionary<TKey, TValue> clone = new CloneableDictionary<TKey, TValue>();

        foreach (KeyValuePair<TKey, TValue> pair in this)
        {
            clone.Add(pair.Key, (TValue)pair.Value.Clone());
        }

        return clone;
    }
}

можно тогда клонировать словарь просто путем вызова Clone метод. Конечно, эта реализация требует, что тип значения реализаций словаря ICloneable, но иначе универсальная реализация не практична вообще.

10
ответ дан Compile This 23 November 2019 в 05:35
поделиться

Вы могли всегда использовать сериализацию. Вы могли сериализировать объект, тогда десериализовывают его. Это даст Вам глубокую копию Словаря и всех объектов в нем. Теперь можно создать глубокую копию любого объекта, который отмечен как [сериализуемый], не пишущий специального кода.

Вот два метода, которые будут использовать Двоичную Сериализацию. При использовании этих методов, Вы просто звоните

object deepcopy = FromBinary(ToBinary(yourDictionary));

public Byte[] ToBinary()
{
  MemoryStream ms = null;
  Byte[] byteArray = null;
  try
  {
    BinaryFormatter serializer = new BinaryFormatter();
    ms = new MemoryStream();
    serializer.Serialize(ms, this);
    byteArray = ms.ToArray();
  }
  catch (Exception unexpected)
  {
    Trace.Fail(unexpected.Message);
    throw;
  }
  finally
  {
    if (ms != null)
      ms.Close();
  }
  return byteArray;
}

public object FromBinary(Byte[] buffer)
{
  MemoryStream ms = null;
  object deserializedObject = null;

  try
  {
    BinaryFormatter serializer = new BinaryFormatter();
    ms = new MemoryStream();
    ms.Write(buffer, 0, buffer.Length);
    ms.Position = 0;
    deserializedObject = serializer.Deserialize(ms);
  }
  finally
  {
    if (ms != null)
      ms.Close();
  }
  return deserializedObject;
}
5
ответ дан Shaun Bowe 23 November 2019 в 05:35
поделиться

Метод двоичной сериализации работает нормально, но в моих тестах он оказался в 10 раз медленнее, чем реализация без сериализации клона. Проверял на Dictionary >

3
ответ дан 23 November 2019 в 05:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: