2008-12-05 12 views

Odpowiedz

34

Tak i nie. Jak zauważyli Jeff i inni, wszystkie klasy wyjątków powinny i prawie zawsze podlegać serializacji. Jeśli natkniesz się na określoną klasę wyjątków, której nie można poddać serializacji, jest to prawdopodobnie błąd.

Jednak rozważając możliwość serializacji, należy wziąć pod uwagę zarówno bezpośrednią klasę, jak i wszystkie typy, które są członkami tego typu (jest to proces rekurencyjny). Podstawowa klasa wyjątków ma właściwość Data, która jest typu IDictionary. Jest to problematyczne, ponieważ pozwala użytkownikowi lub kogokolwiek innego dodać dowolny obiekt do wyjątku. Jeśli ten obiekt nie jest możliwy do serializacji, serializacja wyjątku zakończy się niepowodzeniem.

Domyślna implementacja właściwości Data wykonuje pewne podstawowe sprawdzenia, aby zapewnić, że dodawany obiekt jest poddawany serializacji. Ale to jest wadliwy na kilka sposobów

  • Tylko ma najwyższy poziom sprawdzania serializability typu i tej kontroli odbywa się tylko poprzez sprawdzenie Type.IsSerializable (nie 100% stały wyboru).  
  • Własność jest wirtualna. Typ wyprowadzonego wyjątku może przesłonić i użyć tablicy HashTable, która wykonuje 0 sprawdzania.
15

Tak, ale historycznie nie było (gra słów nie przeznaczonych) wyjątki.

Innymi słowy, wszystkie wyjątki powinny być serializable, ale niektóre niestandardowe Wyjątki od kodu strony trzeciej nie możebyć, w zależności od tego, jak są one realizowane.

Na przykład w erze .NET 1.0 wyjątki od oficjalnego dostawcy bazy danych Microsoft Oracle nie podlegały szeregowaniu z powodu błędów w ich kodzie.

+1

Nawet od .Net 4.5, niektóre wyjątki bazy danych OleDB i niektóre wyjątki System.Net nie podlegają de-serializacji z powodu braku wymaganego konstruktora. – ricovox

6

System.Exception implementuje ISerializable, ale potomkowie mogą nie deserializować, jeśli nie implementują poprawnego przeciążonego konstruktora z podpisem (SerializationInfo,StreamingContext).

+1

Ponadto, jeśli wyprowadzony wyjątek nie wywołuje poprawnie base.GetObjectData, informacje o podstawowym wyjątku nie zostaną przekształcone do postaci szeregowej, co spowodowałoby błędy przy dekompresji. W obu przypadkach (brakujący konstruktor lub brak serializacji bazy), serializacja zakończy się pomyślnie, ale dekompresja spowoduje zgłoszenie wyjątku. – ricovox

8

Ta kwestia została już odpowiedział wystarczająco, ale dla programistów, którzy są nowi w C# lub serializacji, myślę, że to jest rzeczywiście bardzo pomocne, aby podkreślić, że w ogóle, Wyjątkiem są NIE serializable!

To może zabrzmieć nieco prowokacyjnie, ale pozwól mi wyjaśnić.

To prawda, że ​​wszystkie wyjątki implementują interfejs ISerializable, ale sugeruje to tylko, że numer powinien być możliwy do przekształcenia w postaci. Ale implementacja interfejsu NIE powoduje, że obiekt jest Serializowalny (co w tym kontekście oznacza, że ​​Wyjątek może być zarówno serializowany i deserializowany).

Najbardziej dokładną odpowiedzią na to pytanie, jak zauważyli inni, jest to, że wiele, ale z pewnością nie wszystkie wyjątki w .Net Framework są Serializowalne.Ale jeśli pytanie używa terminu ".NET Exception" w szerszym zakresie, np. Wyjątek: uzyskany od System.Exception, następnie lepszą i bardziej pomocną odpowiedzią, jeśli chodzi o najlepsze praktyki i unikanie błędów, jest stwierdzenie powyżej, że w ogóle Wyjątki nie są Serializowalne.

Oto dlaczego: Jak już wcześniej wspomniano, aby wyjątek był naprawdę możliwy do Serializacji, musi mieć właściwego konstruktora ctor(SerializationInfo, StreamingContext) i musi być ozdobiony odpowiednim atrybutem. Co ważne, żadne z tych ograniczeń nie powoduje błędów kompilatora, jeśli zostały pominięte!

Co oznacza, że ​​klasa NO pochodząca z wyjątku jest możliwa do przeprowadzenia Serializacji, chyba że zostaną podjęte dodatkowe, opcjonalne (z punktu widzenia kompilatora) kroki.

tj. każdy nieseryjny/nieświadomy programista, który wyprowadza nowy wyjątek, jak poniżej, właśnie stworzył wyjątek, który NIE jest Serializowalny.

class MyNewException : Exception { } 

Visual Studio ma świetny "wyjątek", który pozwala szybko generować nowe wyjątki serializowalne. Ale nawet w tym przypadku nic nie przypomina ani nie pomaga programistom w rzeczywistych seriach właściwości obiektu. Na przykład, nawet jeśli poniższa klasa ma odpowiedni konstruktor i atrybut, właściwość MyNewField nie będzie serializowana bez dodatkowego kodu zarówno w konstruktorze, jak iw GetObjectData.

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

Tak więc, głównym punktem jest to, że jeśli trzeba polegać na właściwej serializacji Exception & deserializacji z jakiegoś powodu powinny być całkowicie świadomi, że jeśli chodzi o jakiegokolwiek kodu niestandardowego lub zespołów, nie ma gwarancji, że będzie działać. Ponadto, ponieważ wymagany konstruktor jest zwykle chroniony, niekoniecznie będzie można łatwo sprawdzić, czy jest on obecny (bez refleksji).

W moich własnych projektach w niektórych punktach stworzyłem wyjątek "Serwery proxy", który może przechowywać niektóre informacje (np. Wiadomość itp.) Z Wyjątków, które same nie są przekształcalne. Mogą one służyć do serializowania niektórych informacji lub alternatywnie do deserializacji danych zapisanych przez wyjątek, który nie ma odpowiedniego konstruktora.

Powiązane problemy