关于泛型的两个简单问题。
以下两个函数定义是否相同?
FunctionA(Exception ex);
FunctionB<T>(T ex) where T : Exception;
通用实现(FunctionB)是否优于正常实现(FunctionA)?
答案 0 :(得分:3)
看到这个问题:
Difference between generic argument constrained to an interface and just using the interface
答案 1 :(得分:2)
以下内容实际上是相同的(结果):
catch (Exception e)
{
FunctionA(e);
FunctionB(e);
}
但如果你这样做,那就不一样了:
catch (ApplicationException e)
{
FunctionB(e);
}
catch (Exception e)
{
FunctionA(e);
}
这是因为FunctionB在编译时被输入到ApplicationException,而对FunctionA的调用将始终将参数向下转换为Exception。根据您对FunctionB的实现,这可能无关紧要,但有些情况可能会有所不同。我想说,根据经验,如果您的方法实现不需要通用实现,那么不要使用它。
以下是一些重要的例子:
public T AddSomeContextToThisException<T>(T ex) where T : Exception
{
ex.Data.Add("Some key", "Some context message");
return ex;
}
public T ThisIsABadIdeaForExceptionsButMaybeAGoodIdeaForOtherTypes<T>(T ex) where T : Exception, new()
{
// do something with ex
return new T();
}
以下示例需要一些额外的上下文代码,因此请查看其下的代码:
private readonly Bar bar = new Bar();
public void HandExceptionOffToSomethingThatNeedsToBeStronglyTyped<T>(T ex) where T : Exception
{
ICollection<T> exceptions = bar.GetCollectionOfExceptions<T>();
exceptions.Add(ex);
// do other stuff
}
public class Bar
{
// value is object, because .net doesn't have covariance yet
private Dictionary<Type, object> listsOfExceptions = new Dictionary<Type, object>();
public ICollection<T> GetCollectionOfExceptions<T>()
{
if (!listsOfExceptions.ContainsKey(typeof(T)))
{
listsOfExceptions.Add(typeof(T), new List<T>());
}
return listsOfExceptions[typeof(T)] as List<T>;
}
}
答案 2 :(得分:2)
在功能内部,没有区别。差异来自外部。如果使用泛型函数,则可以将相同类型的异常返回给调用代码而不是基本Exception
。大多数情况下,这是一个有争议的问题。
答案 3 :(得分:1)
FunctionB与FunctionA相比没有多大优势。但是,两者之间存在明显差异。
使用FunctionA,您可以将任何派生自(或者是)异常的类型传递给函数。
使用FunctionB,您可以将任何派生自T的类型(必须派生自或者是异常)传递给函数。
这意味着根据T的类型,你将有一个更专业的参数,它将限制你可以传递给它的类型,因为参数将被输入为T,而不是Exception。
现在如果T是异常,那么无关紧要,功能是相同的。但是,如果T是InvalidOperationException,则只允许使用InvalidOperationException实例(以及从中派生的类)。
当您想要确保类型的特化而不必求助于不提供所需专业化水平的基类时,这通常是您想要的。