C#为什么不推断我的泛型类型?
我在泛型方法中有很多有趣的乐趣(希望有乐趣)。在大多数情况下,C#类型推断足够聪明,可以找出必须在我的泛型方法上使用哪些泛型参数,但是现在我有了一个设计,其中C#编译器没有成功,而我相信它可以成功找到正确的类型。
谁能告诉我在这种情况下编译器是否有点笨,还是有一个很明显的原因为什么它不能推断我的通用参数?
这是代码:
类和接口定义:
interface IQuery<TResult> { }interface IQueryProcessor
{
TResult Process<TQuery, TResult>(TQuery query)
where TQuery : IQuery<TResult>;
}
class SomeQuery : IQuery<string>
{
}
一些无法编译的代码:
class Test{
void Test(IQueryProcessor p)
{
var query = new SomeQuery();
// Does not compile :-(
p.Process(query);
// Must explicitly write all arguments
p.Process<SomeQuery, string>(query);
}
}
为什么是这样?我在这里想念什么?
这是编译器错误消息(我们的想象并不多):
无法从用法中推断方法IQueryProcessor.Process(TQuery)的类型参数。尝试显式指定类型参数。
我认为C#应该能够推断出它的原因是由于以下原因:
- 我提供了一个实现的对象
IQuery<TResult>
。 - 该
IQuery<TResult>
类型实现的唯一版本是IQuery<string>
,因此TResult必须是string
。 - 利用此信息,编译器将具有TResult和TQuery。
对我来说,最好的解决方案是更改IQueryProcessor
接口并在实现中使用动态类型:
public interface IQueryProcessor{
TResult Process<TResult>(IQuery<TResult> query);
}
// Implementation
sealed class QueryProcessor : IQueryProcessor {
private readonly Container container;
public QueryProcessor(Container container) {
this.container = container;
}
public TResult Process<TResult>(IQuery<TResult> query) {
var handlerType =
typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult));
dynamic handler = container.GetInstance(handlerType);
return handler.Handle((dynamic)query);
}
}
IQueryProcessor
现在,该界面接受一个IQuery<TResult>
参数。这样,它可以返回a
TResult
,这将从消费者的角度解决问题。我们需要在实现中使用反射来获得实际的实现,因为需要具体的查询类型(在我的情况下)。但是这里有动态类型来进行救援,这将为我们做反思。您可以在本文中阅读有关此内容的更多信息。
回答:
一群人指出,C#不会基于约束进行推理。这是正确的,并且与问题有关。通过检查 参数 及其对应的 形式参数类型 来进行推断,这是推断信息的唯一来源。
然后,很多人都链接到这篇文章:
http://blogs.msdn.com/b/ericlippert/archive/2007/11/05/c-3-0-return-type-
inference-does-not-work-on-member-
groups.aspx
那篇文章既过时又与这个问题无关。这是过时的,因为它描述了我们在C#3.0中做出的设计决策,然后在C#4.0中撤销了该决策,主要是基于对该文章的回答。我刚刚在文章中添加了对此效果的更新。
这无关紧要,因为本文涉及 从方法组参数到泛型委托形式参数的返回类型推断 。那不是原始海报问的情况。
我要阅读的相关文章是这样的:
http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-
part-of-the-
signature.aspx
更新:我听说有消息说C#7.3稍微改变了何时应用约束的规则,使上述已有十年历史的文章不再准确。有空的时候,我将回顾一下以前同事所做的更改,看看是否值得在我的新博客上发布更正;在此之前,请谨慎使用,并查看C#7.3的实际操作。
以上是 C#为什么不推断我的泛型类型? 的全部内容, 来源链接: utcz.com/qa/405709.html