考虑以下功能:
public void DoSomething<TSource>(TSource data)
{
// ...
}
在C#中,编译器可以通过检查方法的参数隐式推断出TSource
的类型:
DoSomething("Hello") // Works fine. DoSomething<string>("Hello") is called.
为什么我们不能在有通用返回值时这样做?
例如:
public TResult DoSomething<TResult, TSource>(TSource data)
{
// ...
}
TResult
无法推断(我理解为什么),但编译器肯定可以推断TSource
的类型,可以吗?
但是,这不会编译:
int result = DoSomething<int>("Hello"); // This should call DoSomething<int,string>("Hello")
答案 0 :(得分:3)
这不是编译器的问题 - C#要求您明确指定所有类型参数或让它推断所有类型参数。
使用您尝试过的语法没有中间立场,我想是因为如果你有这样的通用方法:
public void DoSomething<T1, T2>(T1 data, T2 data)
{
// ...
}
你用它就是这样:
var obj1 = "Hello!";
var obj2 = "Hello?";
DoSomething<IEnumerable<char>>(obj1, obj2);
最后一行可以是两个同样有效的东西的简写:
DoSomething<string, IEnumerable<char>>(obj1, obj2);
DoSomething<IEnumerable<char>, string>(obj1, obj2);
必须采用不同的语法(如<string, ?>
)或其他推理规则,以使像这样的案例有意义且不含糊不清。我想设计团队认为它不值得。
请注意,如果您确实需要部分泛型类型推断,则有一种将调用拆分为两个调用的常见模式,其中一个辅助对象用于保存调用之间的信息。这基本上是currying,适用于类型参数。
我将以使用公共接口和私有实现的形式呈现模式,但如果您不关心这一点,则可以完全跳过该接口。
public TResult DoSomething<TResult, TSource>(TSource data)
{
// ...
}
会变成:
public IWrapper<TSource> DoSomething<TSource>(TSource data)
{
return new WrapperImplementation<TSource>(data);
}
其中:
public interface IWrapper<T>
{
TResult Apply<TResult>();
}
class WrapperImplementation<T> : IWrapper<T>
{
private readonly T _source;
public WrapperImplementation(T source)
{
_source = source;
}
public TResult Apply<TResult>()
{
// ...
}
}
用法是:
DoSomething("Hello").Apply<int>();