c# 溢出抛异常_c# - 在C#中重新抛出异常的正确方法是什么? [重复] - 堆栈内存溢出...

我知道这是一个老问题,但我会回答它,因为我不得不在这里不同意所有的答案。

现在,我同意大多数时候你要么做一个简单的throw ,尽可能多地保存关于出错的信息,或者你想抛出一个新的异常,可能包含它作为内部异常,或不,取决于您想要了解导致它的内部事件的可能性。

但有一个例外。 在某些情况下,方法将调用另一个方法,并且在内部调用中导致异常的条件应被视为外部调用上的相同异常。

一个示例是使用另一个集合实现的专用集合。 假设它是一个包含List但是拒绝重复项的DistinctList 。

如果有人在您的集合类上调用ICollection.CopyTo ,它可能只是在内部集合上直接调用CopyTo (例如,所有自定义逻辑仅应用于添加到集合或设置它)。 现在,该调用将抛出的条件与您的集合应该抛出的条件完全相同,以匹配ICollection.CopyTo的文档。

现在,你可能根本就没有抓住这个执行,让它通过。 这里虽然用户在调用DistinctList上的内容时从List获得异常。 不是世界末日,但您可能希望隐藏这些实现细节。

或者您可以自己检查:

public CopyTo(T[] array, int arrayIndex)

{

if(array == null)

throw new ArgumentNullException("array");

if(arrayIndex < 0)

throw new ArgumentOutOfRangeException("arrayIndex", "Array Index must be zero or greater.");

if(Count > array.Length + arrayIndex)

throw new ArgumentException("Not enough room in array to copy elements starting at index given.");

_innerList.CopyTo(array, arrayIndex);

}

这不是更糟糕的代码,因为它是样板文件,我们可以从CopyTo其他实现中复制它,它不是一个简单的传递,我们必须自己实现它。 仍然,它不必要地重复将在_innerList.CopyTo(array, arrayIndex)完成的完全相同的检查,所以它添加到我们的代码中的唯一的东西是6行,其中可能存在错误。

我们可以检查并包装:

public CopyTo(T[] array, int arrayIndex)

{

try

{

_innerList.CopyTo(array, arrayIndex);

}

catch(ArgumentNullException ane)

{

throw new ArgumentNullException("array", ane);

}

catch(ArgumentOutOfRangeException aore)

{

throw new ArgumentOutOfRangeException("Array Index must be zero or greater.", aore);

}

catch(ArgumentException ae)

{

throw new ArgumentException("Not enough room in array to copy elements starting at index given.", ae);

}

}

对于可能存在错误的新代码而言,情况更糟。 而且我们没有从内心异常中获得一些东西。 如果我们将null数组传递给此方法并接收ArgumentNullException ,我们将不会通过检查内部异常并了解对_innerList.CopyTo的调用是否传递了一个空数组并抛出ArgumentNullException来学习任何东西。

在这里,我们可以做我们想要的一切:

public CopyTo(T[] array, int arrayIndex)

{

try

{

_innerList.CopyTo(array, arrayIndex);

}

catch(ArgumentException ae)

{

throw ae;

}

}

如果用户使用不正确的参数调用它,我们期望必须抛出的每个异常将被重新抛出正确抛出。 如果这里使用的逻辑中存在一个错误,那么它就是两行中的一行 - 要么我们错误地决定这种方法是否有效,或者我们错误地将ArgumentException作为查找的异常类型。 这是catch块可能拥有的唯一两个bug。

现在。 我仍然同意大多数时候你要么普通throw; 或者您想构建自己的异常,以便从相关方法的角度更直接地匹配问题。 像上面这样的情况,像这样的重新投掷更有意义,还有很多其他情况。 举一个非常不同的例子,如果使用FileStream和XmlTextReader实现的ATOM文件读取器收到文件错误或无效的XML,那么它可能想要从这些类中获得完全相同的异常,但它应该看起来调用者是AtomFileReader抛出FileNotFoundException或XmlException ,因此他们可能是类似重新抛出的候选者。

编辑:

我们也可以将两者结合起来:

public CopyTo(T[] array, int arrayIndex)

{

try

{

_innerList.CopyTo(array, arrayIndex);

}

catch(ArgumentException ae)

{

throw ae;

}

catch(Exception ex)

{

//we weren't expecting this, there must be a bug in our code that put

//us into an invalid state, and subsequently let this exception happen.

LogException(ex);

throw;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值