我正在尝试编写一个通用的辅助方法,它可以调用方法并处理异常(如果有的话)。
该方法应该能够接受List
个可接受的Exception
类型,并以特定方式处理它们。对于其他类型的异常,它将以不同的方式处理。
这是方法的简化版本
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;
}
}
此处我将允许的例外类型指定为TAllowedException
。这很好用。但是,这只接受一个Exception_Type
。我怎样才能传递List<Exception_Type>
?
答案 0 :(得分:4)
您不能将类型列表作为类型参数传递给泛型方法。
为什么不简单地将一组类型作为常规参数传递?
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));
使用它也有点棘手。我们当然可以传递异常实例,但创建实例只是为了获取它的类型是没有意义的。我们可以使用强制类型null
来传递强制类型default(T)
或使用new ExceptionCollection { default(ArgumentNullException), default(ArgumentException) };
:
ALTER TABLE book ADD FULLTEXT(name);
我仍然认为在这种特殊情况下,没有必要验证类型集合。可能还有其他情况需要约束的类型集合 - 然后上面的解决方案就可以了。