我可以重载 throw 关键字吗?

Can I overload the throw keyword?

我想重载 throw 关键字以捕获从 Exception 继承的 class 并让它在实际抛出之前执行一些日志记录和其他操作。这可能吗?还是我必须使用常规函数?

我试过:

public class cSilException : Exception
    {
        private string m_strMsg;

        public override void throw(cSilException ex)
        {

        }
...
...
}

您要做的是向您的异常添加一个构造函数,并在该构造函数中执行您需要执行的任何操作。

public class cSilException : Exception
{
    //constructor
    public cSilException()
    {
        // do stuff here
    }
}

你的"overloading the throw keyword"概念很,呃,怎么说呢,迷幻

当然,正如许多人指出的那样,如果您打算做日志记录之类的事情,最好避免这样做。 Alois Kraus 发布了另一个答案并提出了很好的建议。

您不能重载 throw 它是语言的组成部分(不是 class 的成员)

如果你想处理一个特定的异常,你应该catch那个异常:

try
{
    // your code, which throws some exceptions
}
catch(cSilException csEx)
{
   // handle csEx
   throw;  // rethrow this exception
}
catch(Exception ex)
{
   // handle all other exceptions
}

此代码在与所有其他异常不同的代码块中捕获特殊异常cSilException

查找 Exception class 的方法和成员。您可以像这样为 cSilException 定义构造函数

public cSilException(string message)
{
    Message = message;
}

catch (cSilException ex)Console.WriteLine(ex.Message);

我不建议在异常的构造函数中记录任何内容,因为它违反了单一责任原则并且被认为是糟糕的设计。此外,创建异常的事实并不一定意味着它已被抛出,此外,可以捕获并重新抛出异常 - 这些事情可能会导致不正确的日志消息。

相反,您可以使用应用程序范围的异常处理程序,它将根据您预定义的策略处理异常。例如,您可以查看 Enterprise Library Exception Handling Block and specifically this section.

注册事件 AppDomain.FirstChanceException. 在实际抛出之前,您会得到所有异常。在事件处理程序中,您可以检查 exception 并执行所需的日志记录。

没有魔法也没有糟糕的设计。

class Program
{
    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
        DoBadThings();
    }

    private static void DoBadThings()
    {
        DoOneLevelBelow();
    }

    private static void DoOneLevelBelow()
    {

        for(int i=0;i<10;i++)
        {
            try
            {
                if (i == 5)
                {
                    var invalidCast = (string)((object)i);
                }
                else
                {
                    throw new InvalidTimeZoneException();
                }
            }
            catch
            {

            }
        }
    }

    static void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
    {
        if( e.Exception is InvalidCastException)
        {
            LogInvalidCast((InvalidCastException)e.Exception);
        }
    }

    private static void LogInvalidCast(InvalidCastException invalidCastException)
    {
        Console.WriteLine("Got Invalid cast: {0}", invalidCastException);
    }

这将导致:

Got invalid cast: System.InvalidCastException: The object of the type "System.Int32" cannot be converted to "System.String". at ThrowTest.Program.DoOneLevelBelow() in d:\Media\Blog\ThrowTest\Program.cs:line 31.

请注意,由于您在堆栈展开之前收到异常,因此您只会看到它确实发生的方法,而不是调用方法,因为堆栈尚未展开。 如果你想要完整的调用堆栈,你可以使用 Environment.StackTrace 来获取所有堆栈帧。