obsługa wyjątku w klasie

0

Witam
Mam taki problem: Chce dodać obsługę wyjątku FormatException podczas konwertowania stringu do tablicy.
Ostatnia kolumna może zawierać tylko 2 różne cyfry i jeśli jest więcej innych cyfr to debuger pokazue mi błąd FormatEception.
Dodałem try i catch i wszystko teraz jest ok, jednak chciałbym poinformować użytkownika że dany string jest niepoprawny.
Jednak w catch nie moge wpisać: MessageBox.Show("Komunikat"); gdyż metoda ta należy do innej klasy niż form1.
W jaki sposób mógłbym wyświetlić taki komunikat?

Klasa z metodą konwertująca:

public void wczytaj(string tekst)
        {
            try
            {
                double kl1 = 0, kl2 = 0;
                string[] wiersze = tekst.Split('\n');

                for (int i = 0; i < w; i++)
                {
                    string wiersz = wiersze[i];
                    string[] kolumny = wiersz.Trim().Split(' ');

                    for (int j = 0; j < k; j++)
                    {
                        this.tab[i, j] = double.Parse(kolumny[j]);
                    }
                    kl1 = this.tab[0, k - 1];
                    if (this.tab[i, k - 1] != kl1) kl2 = this.tab[i, k - 1];
                }
                if (kl1 < kl2)
                {
                    this.klasa1 = (int)kl1;
                    this.klasa2 = (int)kl2;
                }
                else
                {
                    this.klasa1 = (int)kl2;
                    this.klasa2 = (int)kl1;
                }
            }
            catch (FormatException)
            {
                
            }
            
        }
 

Wywołanie na Form1:


tab = new Tablica(a,b);

tab.wczytaj(text_string);
 
1
  1. nie łapiesz wyjątku w wczytaj, tylko w form1 na jej wywołaniu
  2. wyrzucasz wyjątek wyżej, tego samego typu, lub inny
  3. zwracasz z metody jakiś komunikat
1

Pkt 1. massthera wg mnie:

tab = new Tablica(a,b);

try 
{
    tab.wczytaj(text_string);
}
catch (SeriousException sex)
{
   // ...
}
0

próbuje tak:

 public void wczytaj(string tekst)
        {
            try
            {
                double kl1 = 0, kl2 = 0;
                string[] wiersze = tekst.Split('\n');

                for (int i = 0; i < w; i++)
                {
                    string wiersz = wiersze[i];
                    string[] kolumny = wiersz.Trim().Split(' ');

                    for (int j = 0; j < k; j++)
                    {
                        this.tab[i, j] = double.Parse(kolumny[j]);
                    }
                    kl1 = this.tab[0, k - 1];
                    if (this.tab[i, k - 1] != kl1) kl2 = this.tab[i, k - 1];
                }
                if (kl1 < kl2)
                {
                    this.klasa1 = (int)kl1;
                    this.klasa2 = (int)kl2;
                }
                else
                {
                    this.klasa1 = (int)kl2;
                    this.klasa2 = (int)kl1;
                }

                int a = 0, b = 0, c;

                for (int i = 0; i < w; i++)
                {
                    if (this.tab[i, k - 1] == klasa1) ++a;
                    if (this.tab[i, k - 1] == klasa2) ++b;
                }
                if (a > b) c = b;
                else c = a;

                this.max_Klasyfikator = c;
            }
            catch(Exception e)
            {
                blad = e.Message;
                
            }

i na form1:

 try
                    {
                        trn.wczytaj(text);
                    }
                    catch
                    {
                        MessageBox.Show(trn.blad);
                    }

Jednak na form1 w przypadku błędu nic się nie dzieje i string jest normalnie wczytywany
jeśli usunę try i catch z metody wczytaj to wtedy zawsze podczas wczytywania złego stringu debuger wyświetla mi błąd w metodzie wyswietl();

(btw kompilator nie rozpoznaje u mnie polecenia: SeriousException),

0
wierzbiks napisał(a)

i na form1:

 try
                    {
                        trn.wczytaj(text);
                    }
                    catch
                    {
                        MessageBox.Show(trn.blad);
                    }

A cóż to za przedziwna konstrukcja?
Kto Ci powiedział, że tak się używa try-catch? Skąd wiesz, że w catch obiekt trn w ogóle będzie istniał? Czemu ten obiekt miałby mieć w sobie jakieś informacje o błędzie? Przecież do tego są obiekty klas wyjątków. :|

 
try
{
    trn.wczytaj(text);
}
catch(Exception ex)
{
     MessageBox.Show(ex.Message);
}
</quote>

(btw kompilator nie rozpoznaje u mnie polecenia: SeriousException),

To tak jak ten gość, który nie miał metody DoSomething(). [rotfl]

0

boże... już brak mi sił aby tłumaczyć,
nie ważne co zamieszczę w CATCH na FORM1 bo podczas wywalenia błędu przy wczytywaniu niezgodnego pliku w tym miejscu zatrzymuje się debuger:

public void wczytaj(string tekst)
        {
                double kl1 = 0, kl2 = 0;
                string[] wiersze = tekst.Split('\n');

                for (int i = 0; i < w; i++)
                {
                    string wiersz = wiersze[i];
                    string[] kolumny = wiersz.Trim().Split(' ');

                    for (int j = 0; j < k; j++)
                    {
                        this.tab[i, j] = double.Parse(kolumny[j]);      // TUTAJ ZATRZYMUJE SIE DEBUGIER!!
                    }
                    kl1 = this.tab[0, k - 1];
                    if (this.tab[i, k - 1] != kl1) kl2 = this.tab[i, k - 1];
                }
                if (kl1 < kl2)
                {
                    this.klasa1 = (int)kl1;
                    this.klasa2 = (int)kl2;
                }
                else
                {
                    this.klasa1 = (int)kl2;
                    this.klasa2 = (int)kl1;
                }

                int a = 0, b = 0, c;

                for (int i = 0; i < w; i++)
                {
                    if (this.tab[i, k - 1] == klasa1) ++a;
                    if (this.tab[i, k - 1] == klasa2) ++b;
                }
                if (a > b) c = b;
                else c = a;

                this.max_Klasyfikator = c;         
            
        }
 

jednak gdy metoda wczytaj wyglada tak:

public void wczytaj(string tekst)
        {
            try
            {
                double kl1 = 0, kl2 = 0;
                string[] wiersze = tekst.Split('\n');
 
   ....
 
                this.max_Klasyfikator = c;
            }
            catch(Exception e)
            {
                blad = e.Message;
 
            }
 

wtedy debugier nic nie wyrzuca i ładnie obsługuje wyjątek i ja teraz chce dodatkowo poinformować użytkownika o tym wyjątku na FORM1:

 
                    try
                    {
                        trn.wczytaj(text);
                    }
                    catch
                    {
                        MessageBox.Show("NIECH DLA WAS TU BEDZIE BŁĄD ZAMIAST ex.MESSAGE");
                    }

I jak bym nie zapisał opcji CATCH to i tak nigdy nie jest ona wykonywana (nigdy nie wyskakuje żadnen popup), mimo obsłużonego błędu w metodzie wczytaj.
Może teraz ktoś zrozumiał o co mi chodzi...

0
somekind napisał(a)

(btw kompilator nie rozpoznaje u mnie polecenia: SeriousException),

To tak jak ten gość, który nie miał metody DoSomething(). [rotfl]

W c# programuje od kilkunastu dni i nie wiedziałem że pisząc SeriousException chodziło mu o "poważny wyjątek" a nie o takową składnie, skoro podałem że chodziło mi dokładnie o wyjątek FormatException :P

0

No to zagadka dla Ciebie, znajdź różnicę między tym kodem, a swoim:

using System;

namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            Test test = new Test();

            try
            {
                test.Wczytaj("lalala");
            }
            catch
            {
                Console.WriteLine("Info o błędzie");
            }


            Console.WriteLine("Koniec!");
            Console.ReadLine();
        }
    }

    class Test
    {
        public string Błąd { get; private set; }

        public void Wczytaj(string text)
        {
            try
            {
                throw new Exception("Zesrała się bida i płacze!");
            }
            catch (Exception e)
            {
                this.Błąd = e.Message;
                throw e;
            }
        }
    }
}
0

ehhhh, brak mi już słów ...
próbowałem m.in takie sposoby jak ty zaprezentowałeś i wtedy:

class Test
    {
        public string Błąd { get; private set; }
 
        public void Wczytaj(string text)
        {
            try
            {
                throw new Exception("Zesrała się bida i płacze!");
            }
            catch (Exception e)
            {
                this.Błąd = e.Message;
                throw e;                      // DEBUGER WYWALA MI TUTAJ BŁĄD
            }
        }
    } 

Nie wiem czemu debuger nie chce przechwycić błędu na Form1 w sekcji try catch tylko wywala go w metodzie wczytaj() ...

dorzucam jeszcze całą sekcje przycisku wczytaj na Form1:

 private void buttonLoadTRN_Click(object sender, EventArgs e)
        {
            DialogResult result = openFileDialog1.ShowDialog();

            if (result == DialogResult.OK) 
            {
                string file = openFileDialog1.FileName;
                try
                {
                    string text = File.ReadAllText(file);

                    //tworzy wiersze (znak \n nowej lini)
                    string[] wiersze = text.Split('\n');
                    string test = wiersze[0];
                    //tworzy kolumny
                    string[] kolumny = test.Trim().Split(' ');

                   int w1 = wiersze.Length;
                   int k = kolumny.Length;

                    trn = new Macierz(w1,k);


                    try
                    {
                        trn.wczytaj(text);
                    }
                    catch 
                    {
                        MessageBox.Show("Info o błędzie");   //NIGDY NIE WYSKAKUJE
                    }

                }
                catch (IOException)
                {

                }

            }
        }
0

Nie wiem czemu debuger nie chce przechwycić błędu na Form1 w sekcji try catch tylko wywala go w metodzie wczytaj() ...

A ja nie wiem czemu zamiast doczytać o tym jak obsługuje się wyjątki, piszesz kolejnego posta tutaj.

W Twoim kodzie nie przekazywałeś wyjątku z metody wczytaj dalej. Łapałeś go w catch i nie przekazywałeś dalej, dlatego metoda obsługująca przycisk nigdy tego wyjątku nie otrzymała. Aby przekazać wyjątek dalej trzeba użyć właśnie throw.

0

grrr.... wrrr... nie wiem co ci jeszcze mam napisać:
przecież sam podałeś przykład z użyciem throw i ten przykład nie działa, sam próbowałem w ten sposób wcześniej i nie działa,
metoda nie chce przekazać tego wyjątku do FORM1 tylko debugier zatrzymuje sie na poleceniu:
throw e;
w metodzie wczytaj() mimo istnienia obsługi wyjątku try, catch na FORM1

spróbuje łopatologicznie przedstawić przykład mojego problemu:
klasa:

 
public void wczytaj()
        {
        throw new System.ArithmeticException("Niedozwolona operacja arytmetyczna!");  // DEBUGER ZATRZYNUJE SIE W TYM MIEJSCU I WYWALA PROGRAM
        }

form1:

 
                   try
                    {
                        obiekt.wczytaj();
                    }
                    catch (ArithmeticException ee)
                    {
                        MessageBox.Show(ee.Message);    // NIGDY NIE WYSKAKUJE
                    }

Może teraz zrozumiesz o co mi chodzi;

0

Na początek truizm: WKLEIŁEM CI POPRAWNIE KOMPILUJĄCY SIĘ I DZIAŁAJĄCY ZGODNIE Z ZAŁOŻENIAMI KOD OBRAZUJĄCY KORZYSTANIE Z WYJĄTKÓW W C#. TEN KOD DZIAŁA I JEST TO FAKT, Z KTÓRYM NIE MOŻNA DYSKUTOWAĆ.

Jeśli masz z nim jakiś problem, to znaczy, że albo nie potrafisz go skopiować, albo zepsułeś coś innego. Nie rozumiem stwierdzenia "DEBUGER ZATRZYNUJE SIE W TYM MIEJSCU I WYWALA PROGRAM". Znaczy co się dzieje? A czy gdy uruchomisz program bez debuggera również MessageBox się nie wyświetla? Zmieniałeś coś w ustawieniach debuggera w Visual Studio?

0
  1. Debugger się zatrzymuje bo o to chodzi w trybie debug, żeby móc sobie zobaczyć co się posypało!!!!! ale wciśnięcie np. F5 powinno polecieć dalej
  2. Dlaczego używasz double.Parse? I dlaczego robisz to nieumiejętnie? Takie parsowanie i łapanie wyjątków jest zwyczajnie głupie, tzw. sterowanie za pomocą wyjątków. Czemu głupie? bo bez sensu produkujesz wyjątek, co jest kosztowne. Jest świetna metoda TryParse, której powinieneś użyć i jeśli się nie uda, to np. wyjdź z metody z komunikatem błędu.
    Jeśli już chcesz jednak mieć przetwarzanie w ten sposób, to zrób to jak należy. Somekind ci napisał jak.
  3. Jak napisał somekind łapiąc wyjątek powinieneś bazować na tym co w wyjątku jest (tzn. na jego Message, ewentualnie na innych polach)

mała uwaga do kodu:

catch (Exception e)
            {
                this.Błąd = e.Message;
                throw e;                      // DEBUGER WYWALA MI TUTAJ BŁĄD
            }

w catch nie wyrzucajcie błędu przez throw e; tylko przez throw;
Jak różnica? jak re-wyrzucisz przez throw e; to wyczyści się stacktrace, więc jeśli gdzieś to później zalogujesz do interpretacji, to uda ci się dojść tylko do catch, z którego re-wyrzuciłeś wyjątek. Będziesz musiał dogłębnie przetrzepać cały kod w try żeby dojść do tego gdzie był błąd. A jeśli zalogowany został np. NullReferenceException, a w try jest trochę linijek kodu, to szukaj wiatru w polu :)

0

już rozwiązałem problem...
miałem dwa przyciski wczytujące macierze na form1, pisałem obsługę błędu dla przycisku nr2, a sprawdzałem ją klikając przycisk nr1, który nie miał obsługi błędu ...<głupek>
Czyli w zasadzie dwie pierwsze odpowiedzi wystarczyły.

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