C# 是否可以/应该在c switch语句中抛出异常?

C# 是否可以/应该在c switch语句中抛出异常?,c#,exception,switch-statement,throw,C#,Exception,Switch Statement,Throw,我有一个insert查询,返回一个int。基于该int,我可能希望抛出一个异常。在switch语句中这样做合适吗 switch (result) { case D_USER_NOT_FOUND: throw new ClientException(string.Format("D User Name: {0} , was not found.", dTbx.Text)); case C_USER_

我有一个insert查询,返回一个int。基于该int,我可能希望抛出一个异常。在switch语句中这样做合适吗

 switch (result)
        {

            case D_USER_NOT_FOUND:
                throw new ClientException(string.Format("D User Name: {0} , was not found.", dTbx.Text));
            case C_USER_NOT_FOUND:
                throw new ClientException(string.Format("C User Name: {0} , was not found.", cTbx.Text));
            case D_USER_ALREADY_MAPPED:
                throw new ClientException(string.Format("D User Name: {0} , is already mapped.", dTbx.Text));
            case C_USER_ALREADY_MAPPED:
                throw new ClientException(string.Format("C User Name: {0} , is already mapped.", cTbx.Text));
            default:

                break;
        }
我通常会在开关中添加break语句,但它们不会被击中。这是一个糟糕的设计吗?请与我分享任何意见/建议

谢谢,
~ck在圣地亚哥

我不太同意你的变量命名约定;,但我不明白为什么你做的不合适。这似乎是一种将错误从一种媒介转换为另一种媒介的相当优雅的方式


我假设您的insert查询是某种形式的存储过程。

我认为这是可以的。似乎您正在使用switch语句将返回代码映射到异常。只要案例不太多,这就不是问题。

如果可能,最好是在设置失败结果的地方抛出,否则最终必须同时执行结果检查和抛出。当然,这可能是不可能的


另外,我会将您的错误字符串转换为带有占位符的资源或常量,这样,如果您想更改措辞,就不必更改多个位置。

没问题。。。为什么这是一个糟糕的设计

或者,由于异常类型在所有情况下都是相同的,因此可以为错误消息构造一个查找表。这将为您节省一些代码重复。例如:

static private Dictionary<int, string> errorMessages;
static
{
    // create and fill the Dictionary
}

// meanwhile, elsewhere in the code...
if (result is not ok) {
    throw new ClientException(string.Format(errorMessages[result], cTbx.Text, dTbx.Text));
}

在消息本身中,您可以使用{0}、{1}等选择适当的参数。

您所采用的方法没有问题。Switch语句比if/then语句更容易阅读,而且可能更快。您可以做的另一件事是在

Dictionary<Result_Type, Exception>
然后从那里提取异常。如果您有很多switch语句,这将使代码更加紧凑,如果需要,您可以在运行时添加和删除它们。

为什么不呢

Anders Hejlsberg等人出版的《C编程语言》第三版第362页:

switch部分的语句列表通常以break、goto case或goto default语句结尾,但允许任何使语句列表的端点不可访问的构造。[…]同样,throw或return语句总是将控制权转移到其他地方,并且永远不会到达其终点。因此,以下示例是有效的:

switch(i) {
case 0:
    while(true) F();
case 1:
    throw new ArgumentException();
case 2:
    return;
}

我认为在你的情况下使用开关没有任何问题


更强有力的考虑应该是例外本身是否合适。通常,只有在出现超出预期行为范围的情况时才应使用异常。异常不应用作程序流逻辑。在您的情况下,根据我看到的代码,您可能可以使用它们。

也许我不同意这里的所有答案

我宁愿将结果传递给ClientException类,让它决定需要显示什么字符串,而不是到处都有一个丑陋的开关来创建各种消息,而不是在代码中切换

我的代码如下所示:

throw new ClientException(result, cTbx.Text);

所以,即使您可以在switch…case中抛出错误,您也可以避免这一切,这是我的看法

看起来您正在尝试将返回代码映射到异常。你的意图很清楚,所以我认为这个解决方案很好。在这一点上,ClientException构造函数将具有相同的切换逻辑,但它必须有中断。我否决了,因为这个解决方案只是转移了问题。这并没有造成任何真正的区别。@第七个元素-你说的没有造成任何真正的区别是对的,但在我的解决方案中,代码更易于维护,因为switch…case在ClientException类中&调用者不需要在代码中编写switch…case over&over…除了@Yishai的要点,结果可能并不总是错误代码。@Rowland-在您提到的情况下,是否会出现如下重载:抛出新的ClientExceptionmessage;帮助我已经看到Exception类有各种重载构造函数&我认为这样做是一种很好的实践……字典可能是好的,但它必须是DictionaryYeah,而不是使用字典的最佳示例。如果有什么需要的话,您可能需要存储异常类型,而不是实际的异常本身。不幸的是,存储异常类型不会有多大用处,因为除非在异常上下文中使用一个有点狡猾的介词,否则在给定异常类型的情况下,没有通用的方法,生成该类型的异常。