C# - throw 关键字 throw keyword 我们在上一节中已经看到如何处理由 CLR 自动抛出的异常。 在这里,我们将看到如何手动抛出异常。
可以使用 throw 关键字手动抛出异常。 可以使用 throw 关键字抛出从 Exception 类派生的任何类型的异常。
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
Student std = null;
try
{
PrintStudentName(std);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); // 输出了 Student object is null.
}
Console.ReadKey();
}
private static void PrintStudentName(Student std)
{
if (std == null)
throw new NullReferenceException("Student object is null.");
Console.WriteLine(std.Name);
}
}
在上面的示例中,因为 Student 对象为 null, 所以 PrintStudentName() 方法会引发 NullReferenceException。
请注意, throw 使用 new 关键字创建任何有效异常类型的对象。 throw 必须跟从Excpetion派生出来的类型一起使用。
您还可以从 catch 块重新抛出异常以传递给调用者,并让调用者按照他们想要的方式处理它。 以下示例重新引发异常。
class Program
{
static void Main(string[] args)
{
try
{
Print();
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
Console.ReadKey();
}
private static void Print()
{
Student std = null;
try
{
PrintStudentName(std);
}
catch (Exception ex)
{
throw;
}
}
private static void PrintStudentName(Student std)
{
if (std == null)
throw new NullReferenceException("Student object is null."); //line 36
Console.WriteLine(std.Name);
}
}
在上面的例子中,PrintStudentName() 中发生了异常。 Print()的catch 块仅使用 throw 关键字(而不是 throw ex)重新抛出该异常。 最后在 Main() 方法中处理。 此异常的堆栈跟踪将为您提供此异常发生位置的完整详细信息,我们可以看到异常第一次发生在PrintStudentName。
at ConsoleApp1.Program.PrintStudentName(Student std) in C:\Users\malema.net\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 36
at ConsoleApp1.Program.Print() in C:\Users\malema.net\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 25
at ConsoleApp1.Program.Main(String[] args) in C:\Users\malema.net\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 11
但是如果在Print()当中throw 变成 throw ex的话,这边就被成了异常的引发点。则原始异常的堆栈信息会丢掉。 以下示例演示了这一点。
class Program
{
static void Main(string[] args)
{
try
{
Print();
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
Console.ReadKey();
}
private static void Print()
{
Student std = null;
try
{
PrintStudentName(std);
}
catch (Exception ex)
{
throw ex; //跟上面的例子不一样了
}
}
private static void PrintStudentName(Student std)
{
if (std == null)
throw new NullReferenceException("Student object is null.");
Console.WriteLine(std.Name);
}
}
输出 下面的信息。 会发现第一个位置是在Print()方法了,而不是 PrintStudentName()了。
at ConsoleApp1.Program.Print() in C:\Users\malema.net\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 29
at ConsoleApp1.Program.Main(String[] args) in C:\Users\malema.net\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 11
所以通常如果重出抛出一个相同的异常,我们会直接用throw
而不是throw ex
;
另一个方式是我们把这个exception放到innerException里面
static void Main(string[] args)
{
try
{
Print();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString()); // 外转记录通常是用ToString的方式。可以看到完整的出错信息。
}
Console.ReadKey();
}
private static void Print()
{
Student std = null;
try
{
PrintStudentName(std);
}
catch (Exception ex)
{
throw new Exception("Print error",ex); //包起来
}
}
private static void PrintStudentName(Student std)
{
if (std == null)
throw new NullReferenceException("Student object is null.");
Console.WriteLine(std.Name);
}