类型推断在类的范围内推断,但不是方法,尽管它们是相同的?

时间:2012-11-04 13:31:10

标签: c# c#-4.0 type-inference generic-constraints

好的,我的标题一定非常错误。更多代码,更少的单词:

public class Manager<T> where T : Control, new()
{
    void Manage()
    {
        Do(t => IsVisible(t));
    }

    bool IsVisible(T t)
    {
        return t.Visible;
    }

    S Do<S>(Func<T, S> operation)
    {
        return operation(new T());
    }
}

编译器对Do感到高兴。它可以轻松推断出T类型。现在让我说我有这个:

public static class Util
{
    static void Manage()
    {
        Do(t => IsVisible(t)); //wiggly line here
    }

    static bool IsVisible<T>(T t) where T : Control
    {
        return t.Visible;
    }

    static S Do<S, T>(Func<T, S> operation) where T : Control, new()
    {
        return operation(new T());
    }
}

编译器希望现在显式键入类型。这就是我的想法:

在第一课T很容易被IsVisible方法推断出T重载,T类已知Manager , 没什么大不了。但在第二种情况下,T被指定为方法的通用约束,并且可能更难以推断。确定。

但这也不起作用:

public static class Util
{
    static void Manage()
    {
        Do(t => IsVisible(t)); //still wiggly line
    }

    static bool IsVisible(Control t)
    {
        return t.Visible;
    }

    static S Do<S, T>(Func<T, S> operation) where T : Control, new()
    {
        return operation(new T());
    }
}
  1. 为什么编译器在最后一种情况下不推断T

  2. 更重要的是,最后一个案例与第一个案例有何不同?在第一种情况下,编译器必须从IsVisible方法推断它,然后一直回去检查包含T的类中IsVisible是什么,在最后一种情况下它很容易以IsVisible方式提供。所以我假设第三种情况比第一种情况容易。

1 个答案:

答案 0 :(得分:4)

(第一个案例)

  

编译器对Do感到高兴。它可以很容易地推断出T型。

根本不会推断TT是类的类型参数:

public class Manager<T> where T : Control, new()

(第二个案例)

  

编译器希望现在显式键入类型。

我认为你的意思是在管理代码中:

Do(t => IsVisible(t))

那是对的。 认为T的类型应该在哪里?您如何期望编制者推断它?

(第三种情况,方法为IsVisible(Control t)

  

为什么编译器在最后一种情况下不推断T?

仅从参数中无法做到这一点。听起来你期望它可以解决lambda表达式的主体可以工作的每种类型......并且类型推断根本不起作用。您可以轻松地为编译器提供足够的信息:

 Do((Control t) => IsVisible(t)); 
  

更重要的是,最后一个案例与第一个案例有何不同?

在第一种情况下,T不是Do方法的类型参数。编译器 only 需要推断S,它可以从lambda表达式的返回类型中做到。它不需要对T执行任何推断,因为它已经“已知”。 (它仍然是通用的,但它不是需要为该方法调用推断的东西。)构造T的实例时需要提供Manager的类型首先,它正在有效地推动这一决定。

有关类型推断的所有详细信息,请参阅C#4规范的7.5.2节(或C#3或C#5规范中的等效部分)。我先建议喝一杯浓咖啡,但是:)