C# liskov替换原理与异常处理
它说派生类不应该抛出基类不知道的任何异常,我正在试图找到它是如何工作的,在基类中我抛出System.exception,在派生类中我抛出ArgNullException()。 有人能解释一下吗C# liskov替换原理与异常处理,c#,oop,solid-principles,design-principles,C#,Oop,Solid Principles,Design Principles,它说派生类不应该抛出基类不知道的任何异常,我正在试图找到它是如何工作的,在基类中我抛出System.exception,在派生类中我抛出ArgNullException()。 有人能解释一下吗 class b { virtual public void foo() { try { if (true)
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");
}
}
}
在这种情况下,您将在基类中抛出尽可能少的特定异常(另一个讨论是为什么这样做很糟糕)。在这种情况下,使用子类的任何人都将能够捕获到该异常,无论您抛出的异常有多具体
让我们假设情况正好相反。基类抛出
ArgumentNullException
,子类抛出Exception
。现在,任何只知道基类的人都只能获得ArgumentNullException
的catch块,因为这是他们所期望的。因此,当子类抛出异常时,它们的应用程序将失败
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将违反该假设。可以在这里找到对Liskov替代原理的更好理解附加说明:与C#不同,Java在编译时检查了异常以解决此LSV冲突。基类引发的异常应该是超类引发的异常的子类型。您的示例甚至不会引发任何异常(因为catch块)。
try {
this.foo();
} catch (ArgumentOutOfRangeException e) {
...
}