使用 Func<T> 参数时使用逆变的能力差异
Difference in ability to use contravariance when using a Func<T> parameter
我很好奇为什么在C#中允许以下逻辑
private static void Foo(Func<Exception, string> func)
{
try
{
// ...
}
catch (ArgumentException ex)
{
func(ex);
}
}
而这不是
private static void Foo<T>(Func<T, string> func) where T : Exception
{
try
{
// ...
}
catch (ArgumentException ex)
{
func(ex);
}
}
据我了解,由于 Func<in TArg1, out TResult>
委托自 .NET 4.0 起具有逆变参数,因此第一种情况没有问题,但为什么切换到 constrained 泛型改变了编译器应用这种逆变的能力?
您的第一个函数将编译,但是由于 Func
参数的逆变,您只能传递一个 Func
和一个 Exception
超类型的参数,例如
Func<object, string> f = o => o.ToString();
Foo(f);
第二个例子不是这种情况,它要求你传递一个 Func
和一个 Exception
的子类型的参数,例如
Func<InvalidOperationException> f = o => ...
这不安全。
我很好奇为什么在C#中允许以下逻辑
private static void Foo(Func<Exception, string> func)
{
try
{
// ...
}
catch (ArgumentException ex)
{
func(ex);
}
}
而这不是
private static void Foo<T>(Func<T, string> func) where T : Exception
{
try
{
// ...
}
catch (ArgumentException ex)
{
func(ex);
}
}
据我了解,由于 Func<in TArg1, out TResult>
委托自 .NET 4.0 起具有逆变参数,因此第一种情况没有问题,但为什么切换到 constrained 泛型改变了编译器应用这种逆变的能力?
您的第一个函数将编译,但是由于 Func
参数的逆变,您只能传递一个 Func
和一个 Exception
超类型的参数,例如
Func<object, string> f = o => o.ToString();
Foo(f);
第二个例子不是这种情况,它要求你传递一个 Func
和一个 Exception
的子类型的参数,例如
Func<InvalidOperationException> f = o => ...
这不安全。