5

我在使用 Visual Studio 10(现在也是 11)时遇到了一个奇怪的错误。我有一个扩展方法

public static S Foo<S, T>(this S s) where S : IEnumerable<T>
{
    return s;
}

现在如果我打电话

"".Foo(); // => 'string' does not contain a definition for 'Foo' and no extension method 'Foo' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)

我根本不了解引擎盖下发生了什么。烦人的部分是智能感知列表FooIEnumberable<T>s。充其量它应该给出一个type can't be inferred error.

如果我这样称呼它:

Extension.Foo(""); // => The type arguments for method 'Extension.Foo<S,T>(S)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

为什么在上述情况下无法推断类型?

更多的:

假设我有:

public static S Foo<S, T>(this S s, T t) where S : IEnumerable<T>
{
    return s;
}

如果我打电话:

"".Foo(1);

类型推断在这里非常聪明地告诉我Foo应该返回IEnumerable<int>string不是全部!

因此,如果编译器可以知道Foo期望 char 作为第一个参数,那么为什么我的第一个示例不直接编译呢?换句话说,为什么在第一个示例中编译器知道T在这种情况下是 char?

正如预期的那样,这适用于第二个示例:

"".Foo('l');

我只是想知道为什么不能Tchar第一个示例中那样推断,毕竟 string 是IEnumberable<char>.


编辑:

我从 SLaks 那里得到了答案。但奇怪的是,考虑到编译器在公开可用方法对对象进行操作时也考虑了泛型约束,C# 没有这样做(类型推断)。

换句话说:

public static S Foo<S, T>(this S s)
{
    return s;
}

Foo在所有objects上都可用。

public static S Foo<S, T>(this S s) where S : IEnumerable<T>
{
    return s;
}

Foo在所有IEnumerable<T>s 上都可用,因为它知道 SIEnumerable<T>。所以我在想 C# 甚至会推断出T! 感谢大家!;)

4

1 回答 1

9

类型推理引擎不够聪明,无法做到这一点。

C# 类型推断只查看方法签名
通用约束不是签名的一部分

由于T没有直接在签名中使用,编译器不会推断它。

于 2012-11-13T14:16:54.490 回答