It says that Derived class should not throw any exception which is not known to the Base class, i am trying to find how its work, in the base class i am throwing System.Exception and in Derived i am throwing ArgNullException(). Can someone explain is this is fine

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

In this case you are throwing the least specific exception possible in the base class (why that sucks is another discussion). As in such, anyone using the sub classes will be able to catch that, no matter how specific exception you throw.


Let's say that it had been the other way around. The base class throws ArgumentNullException and the sub class Exception. Now, anyone only knowing about the base class would only have catch blocks for ArgumentNullException as that is what they expect. Their application will therefore fail when the sub class throws 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
        }
    }
}

其他提示

In the code you posted, there is no issue in terms of subtypes, because in both cases you are catching the exception in the same scope that it's thrown. But suppose the derived foo did not have a catch clause, and the base class had the following code:

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

The base class is making the assumption that foo only throws ArgumentOutOfRange, which the derived class would be violating by throwing ArgumentNull.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top