Ausnahmen und Ausnahmebehandlung in C#

1- What is Exception?

Zuerst sehen wir ein Beispiel wie folgend:
Im Beispiel gibt es eine falsche Code. Das ist die Division durch 0. Die Division durch 0 verursacht eine Ausnahme: DivideByZer oException
HelloException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class HelloException
    {
        public static void Main(string[] args)
        {

            Console.WriteLine("Three");

            // This division no problem.
            int value = 10 / 2;

            Console.WriteLine("Two");

            // This division no problem.
            value = 10 / 1;

            Console.WriteLine("One");

            int d = 0;

            // This division has problem, divided by 0.
            // An error has occurred here.
            value = 10 / d;

            // And the following code will not be executed.
            Console.WriteLine("Let's go!");

            Console.Read();
        }
    }
}
Das Ergebni der Durchführung des Beispiel
Sie können die Fehleranmeldung auf dem Bildschirm Console. Die Fehleranmeldung ist sehr klar, sie zeigt wo liegt der Fehler (in welcher Zeile der code.
Sehen Sie das Thread des Programms durch das folgende Beispiel
  • das Programm läuft normal von dem Schritt (1),(2) zum Schritt (5)
  • Der Fehler erscheint im Schritt (6) : Die Division durch 0.
  • Das Programm verlasst die Funktion main, und die Codezeile (7) wird nicht durchgeführt
Wir werden die Code vom oben Beispiel ändern
HelloCatchException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class HelloCatchException
    {
        public static void Main(string[] args)
        {

            Console.WriteLine("Three");

            // This division no problem.        
            int value = 10 / 2;


            Console.WriteLine("Two");

            // This division no problem.     
            value = 10 / 1;


            Console.WriteLine("One");


            int d = 0;

            try
            {
                // This division has problem, divided by 0.
                // An error has occurred here.   
                value = 10 / d;

                // And the following code will not be executed.
                Console.WriteLine("Value =" + value);
            }
            catch (DivideByZeroException e)
            {
                // The code in the catch block will be executed
                Console.WriteLine("Error: " + e.Message);

                // The code in the catch block will be executed
                Console.WriteLine("Ignore...");

            }

            // This code is executed
            Console.WriteLine("Let's go!");


            Console.Read();
        }
    }

}
Und das Beispiel der Durchführung des Beispiel
Wir erläutern der Thread des Programms durch das folgende Beispiel.
  • Die Schritte (1)-(6) sind ganz in Ordnung.
  • Die Ausnahme liegt im Schritt (7), das Problem sind die Division durch 0.
  • Sofort implemiert er den Befehl im Block catch, der Schritt (8) wird ignoriert.
  • Die Schritte (9), (10) werden durchgeführt.
  • Die Schritte (11), (12) werden durchgeführt

2- Exception Hierarchy

Das ist die dezentrale Modelle der Exception im CSharp.
  • die Klasse in der höchsten Niveau ist Exception
  • Die direkten untergeordneten Klassen sind SystemException und AplicationException.

 
Die vorhandenen Exception vom  CSharp werden normalerweise vom SystemException gestammt (derived). Inzwischen sollen die Exception des Benutzer (der Programmer) aus  ApplicationException oder aus ihren untergeordneten Klassen geerbt
Einige eingebauten üblichen Exception im  CSharp.

Exception type

Description

Exception

Base class for all exceptions.

SystemException

Base class for all runtime-generated errors.

IndexOutOfRangeException

Thrown by the runtime only when an array is indexed improperly.

NullReferenceException

Thrown by the runtime only when a null object is referenced.

AccessViolationException 

Thrown by the runtime only when invalid memory is accessed.

InvalidOperationException

Thrown by methods when in an invalid state.

ArgumentException

Base class for all argument exceptions.

ArgumentNullException

Thrown by methods that do not allow an argument to be null.

ArgumentOutOfRangeException

Thrown by methods that verify that arguments are in a given range.

ExternalException

Base class for exceptions that occur or are targeted at environments outside the runtime.

COMException

Exception encapsulating COM HRESULT information.

SEHException

Exception encapsulating Win32 structured exception handling information.

3- Handling exception with try-catch

Wir schreiben eine Exception, die aus der Klasse ApplicationException.geerbt wird
AgeException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
   class AgeException : ApplicationException
   {

       public AgeException(String message)
           : base(message)
       {
       }

   }

   class TooYoungException : AgeException
   {


       public TooYoungException(String message)
           : base(message)
       {

       }

   }


   class TooOldException : AgeException
   {


       public TooOldException(String message)
           : base(message)
       {

       }

   }
}
Und die Klasse  AgeUtils hat die static Methode, die zur Alterüberprüfung zuständig ist
AgeUtils.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class AgeUtils
    {
        // This method checks the age.
        // If age is less than 18, the method will throw an exception TooYoungException
        // If age greater than 40, the method will throw an exception TooOldException
        public static void checkAge(int age)
        {
            if (age < 18)
            {
                // If age is less than 18, an exception will be thrown
                // This method ends here.
                throw new TooYoungException("Age " + age + " too young");
            }
            else if (age > 40)
            {
                // If age greater than 40, an exception will be thrown.
                // This method ends here.
                throw new TooOldException("Age " + age + " too old");
            }
            // If age is between 18-40.
            // This code will be execute.
            Console.WriteLine("Age " + age + " OK!");
        }
    }

}
TryCatchDemo1.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
   class TryCatchDemo1
   {
       public static void Main(string[] args)
       {

       
           Console.WriteLine("Start Recruiting ...");
         
           Console.WriteLine("Check your Age");
           int age = 50;

           try
           {

               AgeUtils.checkAge(age);

               Console.WriteLine("You pass!");

           }
           catch (TooYoungException e)
           {
           
               Console.WriteLine("You are too young, not pass!");
               Console.WriteLine(e.Message);

           }
           catch (TooOldException e)
           {
             
               Console.WriteLine("You are too old, not pass!");
               Console.WriteLine(e.Message);

           }

          Console.Read();

       }
   }

}
Das Beispiel durchführen:
Das folgende Beispiel: Wir fangen die Ausnahme durch eine Ausnahme in der höheren Level.  Auf die höhere Level werden sie diese Ausnahme und alle untergeordneten Ausnahmen fangen.
TryCatchDemo2.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class TryCatchDemo2
    {
        public static void Main(string[] args)
        {
          
            Console.WriteLine("Start Recruiting ...");
       
            Console.WriteLine("Check your Age");
            int age = 15;

            try
            {
                // Here can throw TooOldException or TooYoungException
             
                AgeUtils.checkAge(age);

                Console.WriteLine("You pass!");

            }
            catch (AgeException e)
            {
                // If an exception occurs, type of AgeException
                // This catch block will be execute

                Console.WriteLine("Your age invalid, you not pass");
                Console.WriteLine(e.Message);

            }

            Console.Read();
        }
    }

}
Das Beispiel durchführen

4- try-catch-finally

Oben haben wir den Fang des Fehler durch das Block  try-catch kennengelernt. Die volle Ausnahmebehandlung ist  try-catch-finally.
try {

  // Do something here

} catch (Exception1 e) {

  // Do something here

} catch (Exception2 e) {

  // Do something here

} finally {

  // Finally block is always executed
  // Do something here

}
TryCatchFinallyDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
   class TryCatchFinallyDemo
   {
       public static void Main(string[] args)
       {

           String text = "001234A2";

           int value = toInteger(text);

           Console.WriteLine("Value= " + value);

           Console.Read();

       }

       public static int toInteger(String text)
       {
           try
           {

               Console.WriteLine("Begin parse text: " + text);

               // An Exception can throw here (FormatException).
               int value = int.Parse(text);

               return value;

           }
           catch (FormatException e)
           {
               // In the case of 'text' is not a number.
               // This catch block will be executed.  
               Console.WriteLine("Number format exception: " + e.Message);

               // Returns 0 if FormatException occurs
               return 0;

           }
           finally
           {

               Console.WriteLine("End parse text: " + text);

           }
           
       }
   }

}
Running the example:
Das ist der Threadplan des Programms. Das Block  finally werden immer durchgeführt

5- Exception Wrapping

Wir brauchen einige Klasse für das Beispiel:
  • Person: bezeichnet die Kandidaten einer Firma mit der Information
    • Name, Alter, Geschlecht.
  • GenderException: Die Ausnahme des Geschlecht.
  • ValidateException: Die Ausnahme des Kandidatenbewertung.
  • ValidateUtils: Die Klasse hat die static Methode zur Kandidatenbewertung mit der Kriterien.
    • Die Kriterien: die Alter zwischen 18-40
    • und manlich
Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
  class Person
  {

      public static readonly string MALE = "male";
      public static readonly string FEMALE = "female";

      private string name;
      private string gender;
      private int age;

      public Person(string name, string gender, int age)
      {
          this.name = name;
          this.gender = gender;
          this.age = age;
      }

      public string GetName()
      {
          return name;
      }


      public string GetGender()
      {
          return gender;
      }

      public int GetAge()
      {
          return age;
      }

  }

}
GenderException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
   class GenderException : ApplicationException
   {

       public GenderException(String message)
           : base(message)
       {


       }
   }

}
Die Klasse  ValidateException packt eine andere  Exception ein.
ValidateException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
   class ValidateException : ApplicationException
   {

       // Wrap an Exception
       public ValidateException(Exception e) : base("Something invalid", e)
       {
           
       }
   }

}
ValidateUtils.java
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{

  class ValidateUtils
  {
 
      public static void CheckPerson(Person person)
      {
          try
          {

              // Check age.
              // Valid if between 18-40
              // This method can throw TooOldException, TooYoungException.  
              AgeUtils.checkAge(person.GetAge());

          }
          catch (Exception e)
          {

              // If not valid
              // Wrap this exception by ValidateException, and throw.
              throw new ValidateException(e);

          }

          // If that person is Female, then invalid.
          if (person.GetGender() == Person.FEMALE)
          {

              GenderException e = new GenderException("Do not accept women");
              throw new ValidateException(e);

          }
      }
  }

}
WrapperExceptionDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
 class WrapperExceptionDemo
 {
     public static void Main(string[] args)
     {

         // One participant recruitment.
         Person person = new Person("Marry", Person.FEMALE, 20);

         try
         {

             // Exceptions may occur here.
             ValidateUtils.CheckPerson(person);

         }
         catch (ValidateException wrap)
         {

             // Get the real cause.
             // May be TooYoungException, TooOldException, GenderException
             Exception cause = wrap.GetBaseException();

             if (cause != null)
             {
                 Console.WriteLine("Message: " + wrap.Message);
                 Console.WriteLine("Base Exception Message: " + cause.Message);
             }
             else
             {
                 Console.WriteLine("Message: " + wrap.Message);

             }
         }

         Console.Read();
     }
 }

}
Running the example:

6- Some common exceptions

Jetzt können Sie einige Beispiel mit der üblichen Ausnahmen

6.1- NullReferenceException

Das ist eine der meist üblichen Ausnahmen und verursacht oft den Fehler für das Programm. Die Ausnahme wird geworfen wenn Sie die Funktion aufrufen oder in die Felder eines null Objekt eingreifen.
NullReferenceExceptionDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
   class NullReferenceExceptionDemo
   {
       // For example, here is a method that can return null string.
       public static string GetString()
       {
           if (1 == 2)
           {
               return "1==2 !!";
           }
           return null;
       }

       public static void Main(string[] args)
       {

           // This is an object that references not null.
           string text1 = "Hello exception";

           // Get length of string.
           int length = text1.Length;

           Console.WriteLine("Length text1 = " + length);

           // This is an object that references null.
           String text2 = GetString(); // text2 = null.

           // Get length of string.
           // NullReferenceException will occur here.
           length = text2.Length; // ==> Runtime Error!

           Console.WriteLine("Finish!");


           Console.Read();
       }
   }

}
IN der Praxis wie die Behandlung der anderen Ausnahmen können Sie try-catch benutzen um die Ausnahme zu fangen. Allerdings sollen wir normalerweise überprüfen um vor der Benutzung das nicht-null-Objekt zu guarantieren.

Sie können die obengemeinte Code wie folgend ändern um NullReferenceException:zu vermeiden
// This is a null object.
String text2 = GetString();

// Check to make sure 'Text2' are not null.
// Instead of using try-catch.
if (text2 != null)
{
length = text2.Length;
}
 

6.2- IndexOutOfRangeException

Das ist die geworfene Ausnahme wenn Sie versucht, in die Elemente mit der ungültigen Index auf Array einzugreifen. Zum Beispiel, das Array hat 10 Elemente aber Siegreifen die Elemente mit der Index 20 ein
IndexOutOfRangeExceptionDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class IndexOutOfRangeExceptionDemo
    {
        public static void Main(string[] args)
        {

            String[] strs = new String[] { "One", "Two", "Three" };

            // Access to the element has index 0.
            String str1 = strs[0];

            Console.WriteLine("String at 0 = " + str1);


            // Access to the element has index 5.
            // IndexOutOfRangeException occur here.
            String str2 = strs[5];

            Console.WriteLine("String at 5 = " + str2);

            Console.Read();

        }
    }
}
Um IndexOutOfRangeException zu vermeiden, sollen Sie Array statt der Benutzung  try-catch.prüfen
if (strs.length > 5)
{
String str2 = strs[5];
Console.WriteLine("String at 5 = " + str2);
}
else
{
 Console.WriteLine("No elements with index 5");
}