如何让C#编译器推断泛型类型?

时间:2009-07-30 19:24:49

标签: c# compiler-construction

我有以下方法:

public TResult Get<TGenericType, TResult>()
                          where TGenericType : SomeGenericType<TResult>
                          where TResult : IConvertible {
   //...code that uses TGenericType...
   //...code that sets someValue...
   return (TResult) someValue;
}

现在,此方法的用户必须像这样使用它:

//Notice the duplicate int type specification
int number = Get<SomeGenericType<int>, int>();

为什么我必须在方法定义中指定TResult?编译器已经知道了TResult,因为我在TGenericType中指定了它。理想情况下(如果C#编译器更聪明一点),我的方法看起来像这样:

public TResult Get<TGenericType>()
                          where TGenericType : SomeGenericType<TResult>
                          where TResult : IConvertible {
   //...code that uses TGenericType...
   //...code that sets someValue...
   return (TResult) someValue;
}

因此用户可以像这样简单地使用它:

//Much cleaner
int number = Get<SomeGenericType<int>>();

有办法做我想做的事吗?

2 个答案:

答案 0 :(得分:8)

C#规范不允许推断一半的类型参数。你应该让编译器推断出所有的类型参数(这并不总是适用的,就像你的情况一样)或者手动指定所有这些参数。

更新(回复评论):虽然我不是在C#团队中对你的问题给出一个绝对的答案,但我猜测重载决议的复杂性(已经在意 - 吹嘘;你知道,如果你读过C#规范的那一部分,如果他们想要推断一半的类型被推断而一半不能(特别是考虑到你可以仅通过泛型参数的数量来重载方法的事实)会显着增加。

答案 1 :(得分:1)

这取决于......

如果您只是使用SomeGenericType<TResult>,则可以执行以下操作:

public TResult Get<TResult>() where TResult : IConvertible {
    SomeGenericType<TResult> myInstance = ...
    //...code that sets someValue...
    return (TResult) someValue;
}

在这种情况下,没有必要将第一种类型放在那里。由于您的示例未明确传递SomeGenericType<TResult>作为参数,因此它表明这是可能的。

否则,您需要完全指定所有通用参数。不幸的是,这就是它在C#中的方式。