这是我得到的代码:
class MyMath //start of class MyMath definition
{
// Step 2 - Add exception handling to make sure dividing by 0 does not crash the program.
public static int Divide(int a, int b)
{
return a / b;
} //end of Divide method
} //end of class MyMath
我们收到的关于例外情况的唯一教训是关于 W3 学校的一小部分,但现在这对我并没有多大帮助。我根据我查找的其他示例尝试了不同的变体,但我不断收到无穷无尽的奇怪错误并且不理解它们。这是我开始的:
class MyMath //start of class MyMath definition
{
// Step 2 - Add exception handling to make sure dividing by 0 does not crash the program.
try
{
public static int Divide(int a, int b)
{
return a / b;
} //end of Divide method
}
catch (DivideByZeroException e)
{
Console.WriteLine(e.Message);
}
} //end of class MyMath
错误 CS1519:类、记录、结构或接口成员声明中的标记“try”无效 错误 CS1022:类型或命名空间定义,或预期文件结尾 错误 CS8803:顶级语句必须位于命名空间和类型声明之前。
这可以解决您的编译问题;但这只是故事的一半......
class MyMath //start of class MyMath definition
{
public static int Divide(int a, int b)
{
try
{
return a / b;
}
catch (DivideByZeroException e)
{
Console.WriteLine(e.Message);
throw; // ***this is important***
}
//end of Divide method
}
} //end of class MyMath
暂时忘记确切的 C# 代码和异常。忘记
static
和 class
等等。让我们简化代码并思考发生了什么。
你的函数原来是这样的:
int Divide(int a, int b)
{
return a / b;
}
现在让我们从其他地方调用您的函数。也许我们有另一个函数两次使用您的
MyMath.Divide()
函数。 (忽略数学上这是毫无意义的!)
void MyCalculator_Divide_AndDivideAgain()
{
int startValue = 4;
int firstResult = MyMath.Divide(startValue, 2); // this will return 4/2
int secondResult = MyMath.Divide(firstResult, 2); // this will return 2/2
Console.WriteLine(secondResult); // This should be 1.
}
这一切都很好。现在想象一下,我们做了您最初想要的事情,其中除以零将被捕获并将某些内容打印到屏幕上。为了做这个思想实验,我稍微重写了你的
MyMath.Divide()
,让它更清楚发生了什么:
int Divide(int a, int b) // Let's say that b = 0.
{
int result;
try
{
result = a / b;
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
// Hang on though... what's the value of "result" if there was a divide by zero exception?
// Answer: it doesn't have a value. It doesn't exist.
}
return result; // This is impossible, there's nothing to return. The return value doesn't exist.
}
如果我们现在调用您的代码,传递零,想象一下会发生什么:
void MyCalculator_Divide_AndDivideAgain()
{
int startValue = 4;
int firstResult = MyMath.Divide(startValue, 0); // this will catch the Exception, but the return value doesn't exist any more.
int secondResult = MyMath.Divide(firstResult, 2); // this is now impossible because firstResult never happened.
Console.WriteLine(secondResult); // This is impossible too.
}
那么,如果您在计算
firstResult
时捕获了异常,那么firstResult
的实际值是多少?答案是:它不可能有价值。它不存在。这不是一个有效的计算。
事实上,C# 编译器甚至不会让你这样做。它知道您的代码没有意义,因为除以零捕获没有返回任何内容:
int Divide(int a, int b)
{
try
{
return a / b;
}
catch (DivideByZeroException e)
{
Console.WriteLine(e.Message);
// This causes a compiler error: "not all code paths return a value"
// You still need to return a value, otherwise the result doesn't exist.
}
}
换句话说,你没有决定在例外情况下做什么,这有点“作弊”。您还没有弄清楚如何从函数返回值。您将其打印到屏幕上,但这与做某事不同。并且编译器知道你在作弊!
解决方案是决定你想要用除零来做什么(实际上对于任何异常处理都是如此)。只有2个选择:
在你的例子中,因为它是数学,并且数学有非常明确的“正确和错误”,所以如果除以零,你不能返回一个值。从数学上讲这是没有意义的。所以你必须采取选项2,即决定你不能继续。您的代码将更改为如下所示:
int Divide(int a, int b)
{
try
{
return a / b;
}
catch (DivideByZeroException e)
{
Console.WriteLine(e.Message);
throw; // This is important!
}
}
throw
类似于举起双手并说“我无法进行此计算”。程序将停止。
很多刚开始编程的人认为这是一件坏事;但实际上,当程序出现错误时立即停止是更好的。想象一下,您尝试对除以零的结果进行一些数学计算;可怕的事情将会发生。
现在您已经包含了
throw
那么我们的计算器功能将执行以下操作:
void MyCalculator_Divide_AndDivideAgain()
{
int startValue = 4;
int firstResult = MyMath.Divide(startValue, 0); // this will catch the Exception, but throw, which stops execution.
int secondResult = MyMath.Divide(firstResult, 2); // the throw means this line never executes, so we are safe.
Console.WriteLine(secondResult); // this doesn't happen either, so we're still safe.
}
throw
的缺点是最终你的整个程序将立即退出。您可能会将此称为“崩溃”,尽管实际上这是设计使然。
所以拼图中的最后一块,是你必须在其他地方仍然决定如何处理异常 - 你永远无法避免它。在我们的例子中,也许我们这样做:
void MyCalculator_Divide_AndDivideAgain()
{
try
{
int startValue = 4;
int firstResult = MyMath.Divide(startValue, 0); // this will throw, which skips the next few lines...
int secondResult = MyMath.Divide(firstResult, 2);
Console.WriteLine(secondResult);
}
catch (DivideByZeroException e)
{
// ...and here's where we ultimately catch the exception.
Console.WriteLine("The MyCalculator function isn't valid");
}
}
希望有帮助!