繁体   English   中英

将异常类型列表作为类型参数传递给泛型方法

[英]Passing List of Exception Types as type parameter to generic method

我正在尝试编写一个通用的辅助方法,该方法将调用方法并处理异常(如果有)。

该方法应该能够接受可接受的Exception类型的List ,并以特定方式处理它们。 对于其他类型的异常,它将以不同的方式处理。

这是该方法的非常简化的版本

public static TResult InvokeMethod<TResult, TAllowedException>
                (Func<TResult> func) where TAllowedException : Exception
{
    try
    {
        return func();
    }
    catch (Exception ex)
    {
        if (ex is TAllowedException) //do something
            return default(TResult);
        else //do something else
            throw;
    }
}

在这里,我将允许的Exception Type指定为TAllowedException 这很好。 但是,这仅接受一个Exception_Type 我该如何传递List<Exception_Type>

您不能将类型列表作为类型参数传递给泛型方法。

为什么不简单地将类型的集合作为常规参数传递呢?

public static TResult InvokeMethod<TResult>
        (Func<TResult> func, ICollection<Type> ignoredExceptions)
{
    try
    {
        return func();
    }
    catch (Exception ex)                         
        when (ignoredExceptions != null &&                    
              ignoredExceptions.Any(t => t.IsAssignableFrom(ex.GetType())))
    {
        return default(TResult);
    }
}

如果有人传递的Type也不例外,则不会发生任何不良情况。 我认为没有必要对其进行验证。 该方法仍将正常工作-集合中的异常将被忽略。

调用InvokeMethod(func, new Type[] { typeof(Int32) })的预期行为是什么? func将被执行,并且如果它引发一个Int32异常,则将返回默认结果。 func绝不会抛出Int32异常,因此它已经可以像这样工作,而无需验证ignoredExceptions

BTW不需要将arg作为参数传递。 您可以使用lambda捕获闭包中的arg - () => func(arg) 这将适用于任何数量的参数。

编辑

如果您真的想在编译时限制类型,则必须创建自己的集合,并使用一些奇怪的通用Add方法:

public class ExceptionCollection : IEnumerable<Type>
{
    private readonly List<Type> _exceptions = new List<Type>();        

    public void Add<T>() where T : Exception => _exceptions.Add(typeof(T));
    public IEnumerator<Type> GetEnumerator() => _exceptions.GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_exceptions).GetEnumerator();
}

此类的最大缺点是,它不适用于集合初始值设定项。

也有一种方法使其也可以与集合初始化程序一起使用。 初始化程序需要一个带有一个参数的Add方法,但是它们将很高兴地与泛型Add<T>(T item)方法一起工作。

public void Add<T>(T item) where T : Exception => _exceptions.Add(typeof(T));

使用它也有些棘手。 我们当然可以传递异常的实例,但是仅创建实例来获取其类型毫无意义。 我们可以使用强制类型转换或default(T)来传递强类型的null

new ExceptionCollection { default(ArgumentNullException), default(ArgumentException) };

我仍然认为在这种特殊情况下,不必验证类型的集合。 在其他情况下,如果有必要限制类型的集合,那么上述解决方案就可以了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM