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派生出来的类型一起使用。

重新抛出异常 Re-throwing an Exception

您还可以从 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);
    }
	

上一篇:C# 异常处理
下一篇:C# 自定义异常
最近更新的
...