Rzucanie wyjątków

0

Witam! Napisałem pewną klasę z wykorzystaniem innych. Binarna serializacja danych. Nie za bardzo wiem kiedy rzucać odpowiednio wyjątkami...i czy wgl rzucać, czy to niezbędne do prawidłowej pracy i czy rzucane są w odpowiednich miejscach. Czy lepiej zrobić tak jak poniżej przedstawiam, i później wyłapywać wyjątki przy wykorzystaniu tej klasy?

public static class Serializer {

    public static void BinarySerialize(string path, Object serializedObject)
    {
        BinaryFormatter bf = new BinaryFormatter ();
        try{
            Stream stream = new FileStream(path, FileMode.OpenOrCreate);
            try
            {
                bf.Serialize(stream, serializedObject);
                stream.Close();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message + " Binary serialization error.");
            }
            finally
            {
                stream.Dispose();
            }
        }
        catch(IOException ex)
        {
            throw new IOException(ex.Message + " Saving binary data.");
        }
    }

    public static Object BinaryDeserialize(string path)
    {
        BinaryFormatter bf = new BinaryFormatter ();
        try
        {
            Stream stream = new FileStream(path, FileMode.Open);
            try
            {
                Object deserializedObject = bf.Deserialize(stream);
                stream.Close();
                return deserializedObject;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message + " Binary deserialization error.");
            }
            finally
            {
                stream.Dispose();
            }
        }
        catch (IOException ex)
        {
            throw new Exception(ex.Message + " Loading binary data.");
        }
    }
} 

Czy lepiej tutaj wyłapać je? Wypisać na debug i tyle? I wtedy zrobić np boolowskie funkcje czy serializacja się udala?

0

Nie musisz robić tyle razy try, po prostu wszystko wrzuć w jeden try, a w catch wyłapuj wyjątki odpowiedniego typu IOException, a na końcu same Exception. W finally dodatkowo sprawdź czy stream nie jest nullem (bo wyrzuciło wyjątek IOException) i jeżeli nie jest nullem to daj Dispose.

0

Tak to powinno wyglądać ?

 public static void BinarySerialize(string path, Object serializedObject)
    {
        BinaryFormatter bf = new BinaryFormatter ();
        Stream stream = null;
        try
        {
            stream = new FileStream(path, FileMode.OpenOrCreate);
            bf.Serialize(stream, serializedObject);
            stream.Close();
        }
        catch (IOException ex)
        {
            if (stream != null)
            {
                stream.Dispose();
            }
            throw new IOException(ex.Message + " Binary serialization error.");
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message + " Saving binary data.");
        }
    }

    public static Object BinaryDeserialize(string path)
    {
        BinaryFormatter bf = new BinaryFormatter ();
        Stream stream = null;
        try
        {
            stream = new FileStream(path, FileMode.Open);
            Object deserializedObject = bf.Deserialize(stream);
            stream.Close();
            return deserializedObject;
        }
        catch (IOException ex)
        {
            if (stream != null)
            {
                stream.Dispose();
            }
            throw new IOException(ex.Message + " Binary deserialization error."); 
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message + " Loading binary data.");
        }
    }
0

Może ktoś potwierdzić, że jest to dobrze napisana klasa z wyjątkami? Nie wiem jeszcze czy dobrze rzucam po złapaniu w IO, nie powinno tam być throw new Exception ?

0

Patrząc na ten kod to dałbym jeszcze blok finally i tam zostawił te stream.Dispose(), a przed samym Dispose dał stream.Close(), bo obecnie Dispose wykona się wyłącznie po napotkaniu wyjątku IOException, a Close może się nie wykonać w przypadku wystąpienia wcześniej wyjątku. Wyjątki służą wyłącznie do możliwości obsłużenia sytuacji nieoczekiwanych w programie, przy okazji informują jaka sytuacja wystąpiła i kilka dodatkowych informacji w zależności od wyjątku, więc możesz sobie rzucać jakikolwiek wyjątek chcesz, jeżeli jesteś pewien przyczyny wyjątku to możesz wyrzucić w catch inny, który według Ciebie dokładniej opisuje problem i go odpowiednio spreparować.

3

Nie widzę sensu łapania wyjątku i rzucania takiego samego te parę słów więcej nic nie wnoszą, jak już rzucać dalej to bardziej specyficzny(konkretny), bo teraz równie dobrze tych wszystkich catch mogło by nie być i wyszło by na to samo. Więc albo rzucaj dalej wyjątki własne które są bardziej konkretne albo loguj wyjątek i dodaj konkretny opis. Jak nie możesz zrobić jednego albo drugiego to bym w ogóle nie obsługiwał takiego wyjątku tylko niech leci dalej.

2

czemu nie np tak:


public static void BinarySerialize(string path, Object serializedObject)
{
        var formatter = new BinaryFormatter();
        using(var stream = new FileStream(path, FileMode.OpenOrCreate))
        {
            formatter.Serialize(stream, serializedObject);
        }
}

public static Object BinaryDeserialize(string path)
{
        var formatter = new BinaryFormatter();
        using(var stream = new FileStream(path, FileMode.Open))
        {
            return formatter.Deserialize(stream);
        }
}

?

1

Robiąc tak bardzo utrudniasz rozwiązanie problemu, ponieważ niszczysz pierwotny stacktrace po którym można się dowiedzieć co się faktycznie stało i gdzie.

 throw new Exception(ex.Message + " Saving binary data.");
0

Zrobiłem parę testów i w końcu chyba wiem jak to działa. Dając w catch jakiś specyficzny exception i parę innych zostanie złapany tego typu jaki jest odpowiednio łapany.
W using myslałem, że to nie rzuci dalej wyjątku tylko zachowa go w sobie. A przecież using to tylko try i finally, czyli ten kod zostanie obsłużony, a wyjątek leci dalej! Tego własnie nie rozumiałem! Dzięki!

0

gdy rzucasz swoim wyjątkiem (nie rzucaj nigdy samego Exception, bo tego się nie da indywidualnie złapać) to zawsze oryginalny wyjątek wrzuć do innerException

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0