簡體   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