2008-12-05 7 views

Répondre

34

Oui et non. Comme l'ont souligné Jeff et d'autres, toutes les classes d'exceptions devraient et sont presque toujours sérialisables. Si vous exécutez une classe d'exception particulière qui n'est pas sérialisable, il s'agit probablement d'un bogue. Cependant, lorsque vous envisagez la possibilité de sérialisation, vous devez prendre en compte à la fois la classe immédiate et tous les types qui sont membres de ce type (processus récursif). La classe Exception de base a une propriété Data qui est de type IDictionary. Ceci est problématique car il vous permet, ou à n'importe qui d'autre, d'ajouter un objet à l'exception. Si cet objet n'est pas sérialisable, la sérialisation de l'exception échouera.

L'implémentation par défaut de la propriété Data effectue une vérification de base pour s'assurer qu'un objet ajouté est sérialisable. Mais il est erroné de plusieurs façons

  • ne seul haut niveau pour vérifier sérialisation d'un type et ce contrôle est effectué uniquement en cochant Type.IsSerializable (pas un contrôle solide à 100%).  
  • La propriété est virtuelle. Un type d'exception dérivé peut remplacer et utiliser un Hashtable qui effectue une vérification 0.
15

Oui, mais historiquement il y a eu (sans jeu de mots) exceptions.

En d'autres termes, toutes les exceptions devraient être sérialisable, mais peuvent pas être, selon la façon dont ils sont mis en œuvre certaines exceptions personnalisées à partir du code tiers. Par exemple, à l'ère .NET 1.0, les exceptions du fournisseur de base de données officiel Microsoft Oracle n'étaient pas sérialisables, en raison de bogues dans leur code.

+1

Même à partir de .Net 4.5, certaines exceptions de base de données OleDB et certaines exceptions System.Net ne sont pas dé-sérialisables, en raison de l'absence du constructeur requis. – ricovox

6

System.Exception implémente ISerializable, mais les descendants peuvent ne pas désérialiser s'ils n'implémentent pas le constructeur surchargé correct avec la signature (SerializationInfo,StreamingContext).

+1

En outre, si une exception dérivée n'appelle pas correctement base.GetObjectData, les informations de l'exception de base ne seront pas sérialisées, ce qui entraînerait des erreurs lors de la désérialisation. Dans les deux cas (constructeur manquant ou échec de sérialisation de base), la sérialisation réussira, mais la dé-sérialisation lèvera une exception. – ricovox

8

Cette question a déjà été répondu suffisamment, mais pour les programmeurs qui sont nouveaux C# ou sérialisation, je pense qu'il est vraiment très utile de souligner qu'en général, les exceptions sont pas sérialisable!

Cela peut sembler un peu provocateur, mais laissez-moi vous expliquer.

Il est vrai que toutes les exceptions implémentent l'interface ISerializable, mais cela ne fait que suggérer que doit être être sérialisable. Mais l'implémentation de l'interface ne fait PAS un objet sérialisable (ce qui dans ce contexte implique que l'exception peut être sérialisée à la fois et désérialisée).

La réponse la plus précise à cette question, comme d'autres l'ont souligné, est que beaucoup, mais certainement pas toutes les exceptions .Net Framework sont sérialisables.Mais si la question utilise le terme "Exception .Net" dans une portée plus large, par ex. Une exception dérivée de System.Exception, alors la réponse la meilleure et la plus utile, en termes de meilleures pratiques et d'éviter les bugs, est l'affirmation que j'ai faite plus haut, qu'en général, les exceptions ne sont pas sérialisables. Comme indiqué précédemment, pour qu'une exception soit vraiment sérialisable, elle doit avoir le constructeur approprié ctor(SerializationInfo, StreamingContext) et elle doit être décorée avec l'attribut approprié. Fait important, aucune de ces contraintes ne provoque d'erreurs de compilation si elles sont omises! Cela signifie que NO la classe dérivée de Exception est sérialisable à moins que ces étapes supplémentaires, facultatives (du point de vue du compilateur) soient prises.

I.e. tout codeur non motivé/inconscient qui dérive une nouvelle exception comme ci-dessous vient de créer une exception qui n'est PAS sérialisable. Visual Studio a un excellent extrait "Exception" qui vous permet de générer assez rapidement de nouvelles exceptions sérialisables. Mais même dans ce cas, il n'y a rien pour rappeler ou aider le programmeur à réellement sérialiser les propriétés de l'objet. Par exemple, même si la classe ci-dessous avait le constructeur et l'attribut appropriés, la propriété MyNewField ne serait pas sérialisée sans code supplémentaire dans le constructeur et dans GetObjectData.

class MyNewException : Exception 
{ 
    public MyNewField { get; set; } 
} 

Ainsi, le principal point est que si vous devez compter sur la sérialisation appropriée d'exception & désérialisation pour une raison quelconque, doit être tout à fait conscient du fait que lorsqu'il s'agit de code personnalisé ou assemblées, il n'y a aucune garantie que marchera. De plus, puisque le constructeur requis est généralement protégé, vous ne serez pas nécessairement capable de vérifier facilement qu'il est présent (sans réflexion).

Dans mes propres projets, j'ai créé à certains moments une exception "Proxies" qui peut stocker certaines des informations (par exemple Message etc) à partir d'exceptions qui ne sont pas sérialisables eux-mêmes. Ceux-ci peuvent être utilisés pour sérialiser certaines des informations, ou alternativement pour désérialiser les données écrites par une exception qui n'a pas le constructeur approprié.

Questions connexes