对于泛型方法,我获得了很多实用的乐趣(旨在获得乐趣).在大多数情况下,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的类型参数.过程&lt;查里,

我认为C#能够推断出这一点的原因是:

  1. 我提供了一个实现IQuery<TResult>的对象.
  2. 类型实现的只有IQuery<TResult>个版本是IQuery<string>,因此TResult必须是string.
  3. 有了这些信息,编译器就有了TResult和TQuery.

推荐答案

这篇文章最初是在the question年发布的,并代表OP搬到这里

对我来说,最好的解决方案是更改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>参数.这样它可以返回TResult,这将从消费者的Angular 解决问题.我们需要在实现中使用反射来获得实际的实现,因为需要具体的查询类型(在我的例子中).但是现在有了动态输入来拯救我们,它将为我们做反思.你可以在这article页里读到更多关于这方面的内容.

.net相关问答推荐

如何在dotnet中使用OpenTelemetry Prometheus导出器导出多个版本的度量?

如何将 select 语句详细信息提取到不同的方法中仍然保持Eager 加载?

Msbuild try 构建 msbuild.exe 而不是我的 .csproj 文件

.NET MAUI 的登录页面

IIS 发布 ASP.NET Core 应用程序而不关闭 IIS 网站

比较 C# 中的双精度值

为什么 .Contains 慢?通过主键获取多个实体的最有效方法?

AutoMapper 的替代品

InternalsVisibleTo 属性不起作用

什么版本的 .NET 附带什么版本的 Windows?

哪个更快:清除集合或实例化新的

将接收到的对象转换为 List 或 IEnumerable

.NET 反射的成本是多少?

WCF反序列化如何在不调用构造函数的情况下实例化对象?

所有数组在 C# 中都实现了哪些接口?

在 C# 中,为什么不能将 List 对象存储在 List 变量中

使用+运算符的字符串连接

如何修改 KeyValuePair 值?

在 WPF 中设置 Tab 键顺序

多行 C# 插值字符串文字