使用Func <t>参数时使用逆变的能力差异

时间:2015-08-19 21:29:38

标签: c# contravariance

我很好奇为什么在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以来具有逆变参数,第一种情况不是问题,但为什么切换到约束泛型类型会改变编译器应用这种逆转的能力?

1 个答案:

答案 0 :(得分:3)

您的第一个函数将编译,但由于Func参数的逆转,您只能传递Func参数,该参数是Exception的超类型。

Func<object, string> f = o => o.ToString();
Foo(f);

在第二个示例中不是这种情况,这需要您传递Func参数,该参数是Exception的子类型,例如

Func<InvalidOperationException> f = o => ...

这不安全。