Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Хорошо.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()
являющийся соответственно глубоким клоном также, конечно.
(Примечание: хотя клонирующаяся версия потенциально полезна, для простой мелкой копии конструктор, которого я упоминаю в другом сообщении, является более оптимальным вариантом.)
, Как глубоко Вы хотите, чтобы копия была, и какую версию.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());
(Те не тестируются, но должны работать.)
Для.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
, но иначе универсальная реализация не практична вообще.
Вы могли всегда использовать сериализацию. Вы могли сериализировать объект, тогда десериализовывают его. Это даст Вам глубокую копию Словаря и всех объектов в нем. Теперь можно создать глубокую копию любого объекта, который отмечен как [сериализуемый], не пишущий специального кода.
Вот два метода, которые будут использовать Двоичную Сериализацию. При использовании этих методов, Вы просто звоните
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;
}
Метод двоичной сериализации работает нормально, но в моих тестах он оказался в 10 раз медленнее, чем реализация без сериализации клона. Проверял на Dictionary