2013-08-21 1 views
2

Il est dit que la classe Derived ne devrait pas lancer d'exception qui ne soit pas connue par la classe Base, j'essaie de trouver comment son travail, dans la classe de base, lance System.Exception et Derived Je lance ArgNullException(). Quelqu'un peut-il expliquer est cela est bien beauPrincipe de substitution liskov et gestion des exceptions

class b 
     { 
      virtual public void foo() 
      { 
       try 
       { 
        if (true) 
         throw new System.Exception(); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine("in base"); 

       } 
      } 


     } 
     class a : b 
     { 
      override public void foo() 
      { 
       try 
       { 
        if (true) 
         throw new ArgumentNullException(); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine("in dervied"); 
       } 
      }   

     } 
+0

Exception lancée par la classe de base devrait être une SubType d'exceptions lancées par la classe super. Votre exemple ne lance même pas d'exception (parce que le bloc catch est bloqué). – aknon

Répondre

7
class MyClass 
{ 
    public virtual void Foo() 
    { 
     if (true) 
      throw new System.Exception(); 
     } 
    } 
} 

class MyDerivedClass : MyClass 
{ 
    public override void Foo() 
    { 
     if (true) 
      throw new ArgumentNullException(); 
     } 
    }   
} 


public class Program 
{ 
    public static void Main() 
    { 
     try 
     { 
      // a factory creating the correct 
      // MyClass derived instance 
      var myClass = someFactory.Create(); 

      myClass.Foo(); 
     } 
     catch (Exception) 
     { 
      // will work. 
     } 
    } 
} 

Dans ce cas, vous jetez le moins possible exception spécifique dans la classe de base (pourquoi une autre discussion est succions). En tant que tel, quiconque utilisera les sous-classes sera capable de l'attraper, peu importe l'exception spécifique que vous lancez.


Disons que c'était l'inverse. La classe de base affiche ArgumentNullException et la sous-classe Exception. Maintenant, n'importe qui ne connaissant que la classe de base aurait seulement des blocs catch pour ArgumentNullException car c'est ce à quoi ils s'attendent. Leur application échouera donc lorsque la sous-classe lancera Exception.

class MyClass 
{ 
    public virtual void Foo() 
    { 
     if (true) 
      throw new ArgumentNullException(); 
     } 
    } 
} 

class MyDerivedClass : MyClass 
{ 
    public override void Foo() 
    { 
     if (true) 
      throw new Exception(); 
     } 
    }   
} 


public class Program 
{ 
    public static void Main() 
    { 
     try 
     { 
      // a factory creating the correct 
      // MyClass derived instance 
      var myClass = someFactory.Create(); 

      myClass.Foo(); 
     } 
     catch (ArgumentNullException) 
     { 
      // won't work since the subclass 
      // violates LSP 
     } 
    } 
} 
+0

Note supplémentaire: Contrairement à C#, Java a * vérifié les exceptions * pour résoudre cette violation LSV au moment de la compilation. –

1

Dans le code affiché, il n'y a pas de problème en termes de sous-types, car dans les deux cas, vous attrapez l'exception dans la même portée qu'il est jeté. Mais supposons que la dérivée foon'a pas une clause de capture, et la classe de base a le code suivant:

try { 
    this.foo(); 
} catch (ArgumentOutOfRangeException e) { 
    ... 
} 

La classe de base fait l'hypothèse que seuls foo lancers francs ArgumentOutOfRange, que la classe dérivée violeraient en lançant ArgumentNull.

Questions connexes