2

好吧,我一定是把标题弄错了。更多的代码,更少的文字:

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所以我认为第三种情况比第一种更容易。

4

1 回答 1

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方法的类型参数。编译器需要推断S,它可以从 lambda 表达式的返回类型中完成。它不需要对 执行任何推断T,因为这已经“已知”。(它仍然是通用的,但它不是需要为该方法调用推断的东西。)首先T在构造实例时需要提供类型Manager,因此它有效地推动了该决定。

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

于 2012-11-04T13:48:27.383 回答