我可以捕获c#中泛型参数传入的类型的异常吗?

kha*_*d13 1 .net c# generics exception

以此代码为例 - 我认为当显示TException时,我应该能够"捕获"它并重试我func()适当的次数.但是当我把这些代码放在野外时,即使抛出TException类型的异常,它也会跳过catch子句并冒泡.有人可以解释原因吗?

public static T TryNTimes<T, TException>(Func<T> func, int times) where TException : Exception
{
    if (times <= 0)
        throw new ArgumentException($"TryNTimes: `times` must be a positive integer. You passed in: {times}");

    while (times > 0)
    {
        try
        {
            return func();
        }
        catch (TException)
        {
            if (--times <= 0)
                throw;
        }
    }

    // should never reach here
    return default(T);
}
Run Code Online (Sandbox Code Playgroud)

代码被调用如下:

await RetryUtils.TryNTimes<Task, MyCustomException>(
        () => TryHandleElasticMappingError(dataGridResults, dataGridRecords),
        MyFieldsCount)
    .ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

这是一个异步问题吗?上面的行包含在Try-Catch中,它捕获了Exception我能够验证Exception类型的位置MyCustomException.我可以确认内部catch块(重试方法中的那个)永远不会被击中.

Eri*_*ert 6

这是一个异步问题吗?

如其他答案中所述,是的,这是一个异步问题.

C#中的异步和迭代器块是协同程序.正常的例程可以做三件事:运行完成,抛出或进入无限循环.一个协程可以做第四件事:暂停,以后再恢复.An await是异步块中发生暂停的点; 它yield return位于迭代器块中.

在你的情况下,在协程恢复之前不会发生抛出,此时try它不再有效; try 运行完成的方法因为它不是协程.如果你想要try生效,那么try也必须在异步块中,你必须await在try中.

同样,如果你写道:

IEnumerable<int> Weird(bool b)
{
  if (b) throw new Exception();
  yield return 1;
}

...
IEnumerable<int> x = null;
try
{
  x = Weird(true); // Should throw, right?
}
catch(Exception ex)
{
  // Nope; this is unreachable
}
foreach(int y in x) // the throw happens here!
Run Code Online (Sandbox Code Playgroud)

迭代器块协程开始挂起,直到MoveNext在迭代器上调用才恢复; 它只是返回一个迭代器.异步块协程在await上挂起,但不需要在await上挂起; 等待已经完成的任务被允许跳过暂停.

使用协同程序尝试捕获是棘手的; 小心!