简体   繁体   English

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

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

I'm trying to write a generic helper method that'd call methods and handle exceptions if any. 我正在尝试编写一个通用的辅助方法,该方法将调用方法并处理异常(如果有)。

The method should be able to accept a List of acceptable Exception types, and handle them in a specific way. 该方法应该能够接受可接受的Exception类型的List ,并以特定方式处理它们。 For other type of exceptions, it'll handle differently. 对于其他类型的异常,它将以不同的方式处理。

This is a very simplified version of the method 这是该方法的非常简化的版本

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;
    }
}

Here I'm specifying the allowed Exception Type as TAllowedException . 在这里,我将允许的Exception Type指定为TAllowedException This works fine. 这很好。 But, this accepts only a single Exception_Type . 但是,这仅接受一个Exception_Type How can I pass a List<Exception_Type> instead? 我该如何传递List<Exception_Type>

You cannot pass a list of types as type arguments to a generic method. 您不能将类型列表作为类型参数传递给泛型方法。

Why not simply pass a collection of types as a regular parameter? 为什么不简单地将类型的集合作为常规参数传递呢?

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);
    }
}

If someone passes a Type that is not an exception, nothing bad will happen. 如果有人传递的Type也不例外,则不会发生任何不良情况。 In my opinion there is no need to validate it. 我认为没有必要对其进行验证。 The method will still work correctly - the exceptions in the collection will be ignored. 该方法仍将正常工作-集合中的异常将被忽略。

What is the expected behavior of calling InvokeMethod(func, new Type[] { typeof(Int32) }) ? 调用InvokeMethod(func, new Type[] { typeof(Int32) })的预期行为是什么? The func will be executed, and if it throws an exception that is an Int32 , the default result will be returned. func将被执行,并且如果它引发一个Int32异常,则将返回默认结果。 func will never throw an Int32 exception, so it already works like that without validating ignoredExceptions . func绝不会抛出Int32异常,因此它已经可以像这样工作,而无需验证ignoredExceptions

BTW passing arg as a parameter is not necessary. BTW不需要将arg作为参数传递。 You can use a lambda to capture arg in a closure - () => func(arg) . 您可以使用lambda捕获闭包中的arg - () => func(arg) And this will work with any number of arguments. 这将适用于任何数量的参数。

Edit 编辑

If you really want to restrict the types at compile time, you'd have to create your own collection, with a bit weird generic Add method: 如果您真的想在编译时限制类型,则必须创建自己的集合,并使用一些奇怪的通用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();
}

The biggest disadvantage of this class is that it doesn't work with collection initializers. 此类的最大缺点是,它不适用于集合初始值设定项。

There is a way to make it work with collection initializers too. 也有一种方法使其也可以与集合初始化程序一起使用。 The initializers require an Add method taking one parameter, but they will happily work with a generic Add<T>(T item) method. 初始化程序需要一个带有一个参数的Add方法,但是它们将很高兴地与泛型Add<T>(T item)方法一起工作。

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

Using it is a bit tricky too. 使用它也有些棘手。 We could of course pass instances of exceptions, but it's pointless to create an instance only to get its type. 我们当然可以传递异常的实例,但是仅创建实例来获取其类型毫无意义。 We can pass a strongly-typed null instead, using a cast or default(T) : 我们可以使用强制类型转换或default(T)来传递强类型的null

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

I still think that in this particular case it's not necessary to validate the collection of types. 我仍然认为在这种特殊情况下,不必验证类型的集合。 There might be other cases when a constrained collection of types is necessary - then the above solution is quite ok. 在其他情况下,如果有必要限制类型的集合,那么上述解决方案就可以了。

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

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