繁体   English   中英

liskov替换原则和异常处理

[英]liskov substitution principle and exception handling

它说Derived类不应该抛出Base类不知道的任何异常,我试图找到它的工作方式,在基类中我抛出System.Exception并且在Derived中我抛出了ArgNullException()。 有人可以解释这是好的

 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");
                }
            }           

        }
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.
        }
    }
}

在这种情况下,您可以在基类中抛出最少的特定异常(为什么这很糟糕是另一个讨论)。 就像这样,任何使用子类的人都能够捕获它,无论你抛出多么具体的异常。


让我们说它反过来了。 基类抛出ArgumentNullException和子类Exception 现在,任何只知道基类的人都只有ArgumentNullException catch块,因为这是他们所期望的。 因此,当子类抛出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
        }
    }
}

在您发布的代码中,子类型没有问题,因为在这两种情况下,您都会在抛出异常的范围内捕获异常。 但是假设派生的foo 没有catch子句 ,并且基类具有以下代码:

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

基类假设foo只抛出ArgumentOutOfRange,派生类会抛出ArgumentNull而违反。

可以在此处找到对利斯科夫的替代原则的更好理解
https://stackoverflow.com/search?q=liskov+substitution+principle

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM