Вопрос:
Почему я получаю исключение десериализации «Не найден конструктор для десериализации объекта типа 'SerializeTest.TryMe'" в первой реализации класса, а не во второй?
Ответ:
Документация интерфейса ISerializable
гласит:
Интерфейс ISerializable
подразумевает конструктор с подписью constructor (SerializationInfo information, StreamingContext context)
. Во время десериализации текущий конструктор вызывается только после десериализации данных в SerializationInfo
форматером.
(Давайте назовем constructor (SerializationInfo information, StreamingContext context)
конструктором десериализации.)
Итак, из документации мы знаем, что для классов, которые реализуют ISerializable
, обязателен конструктор десериализации.
Класс Dictionary<TKey, TValue>
реализует ISerializable
и ваш класс TryMe
(из второго образец) наследует Dictionary<TKey, TValue>
. Во время десериализации десериализатор рассматривает TryMe
как класс, который реализует ISerializable
и ищет конструктор десериализации. Десериализатор не может найти его и выдает исключение.
Интерфейс IDictionary<TKey, TValue>
не реализует ISerializable
, поэтому конструктор десериализации не требуется. В этом случае TryMe
может быть десериализовано без конструктора десериализации. Исключение не выдается.
Вопрос:
Кроме проблемы с сериализацией, когда я предпочитаю наследовать IDictionary и когда словарь?
Есть ли канонический способ / правило для этого?
Ответ:
Для сериализации можно наследовать либо Dictionary<TKey, TValue>
, либо IDictionary<TKey, TValue>
. Но если вы наследуете Dictionary<TKey, TValue>
, к вашему классу должен быть добавлен конструктор десериализации.
Когда вы предпочитаете наследовать IDictionary<TKey, TValue>
, а когда Dictionary<TKey, TValue>
? Это зависит от вашей проблемы. решать. В общем случае мы можем рассмотреть два случая:
- Если вам нужно реализовать класс с пользовательской
IDictionary<TKey, TValue>
функциональностью и функциональностью Dictionary<TKey, TValue>
, не удовлетворяющих вашим требованиям, чем вы предпочитаете наследовать IDictionary<TKey, TValue>
, - Если функциональность
Dictionary<TKey, TValue>
удовлетворяет вашим требованиям и, при необходимости, вам нужно изменить или добавить к ней свою собственную функциональность, чем вы предпочитаете наследовать Dictionary<TKey, TValue>
.
Если Вы реализуете IDictionary<TKey, TValue>
, делегируя соответствующие методы Dictionary<TKey, TValue>
, как в первом примере, что вполне вероятно, что вам не нужно реализовывать IDictionary<TKey, TValue>
. В этом случае вы должны наследовать Dictionary<TKey, TValue>
.
// Sample, when it is better to inherit Dictionary<TKey, TValue>
// instead of implementing IDictionary<TKey, TValue>.
[Serializable]
public class TryMe : IDictionary<int, string>
{
Dictionary<int, string> _dictionary = new Dictionary<int, string>();
public IEnumerator<KeyValuePair<int, string>> GetEnumerator()
{
return _dictionary.GetEnumerator();
}
public string this[key]
{
get { return _dictionary[key]; }
}
// Other IDictionary<TKey, TValue> members are implemented the same way.
}