4

次のインターフェイス/クラスがあるとします。

public interface IRequest<TResponse> { }

public interface IHandler<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    TResponse Handle(TRequest request);
}

public class HandlingService
{
    public TResponse Handle<TRequest, TResponse>(TRequest request)
        where TRequest : IRequest<TResponse>
    {
        var handler = container.GetInstance<IHandler<TRequest, TResponse>>();
        return handler.Handle(request);
    }
}

public class CustomerResponse
{
    public Customer Customer { get; set; }
}

public class GetCustomerByIdRequest : IRequest<CustomerResponse>
{
    public int CustomerId { get; set; }
}

次のようなものを書き込もうとすると、コンパイラが正しい型を推測できないのはなぜですか。

var service = new HandlingService();
var request = new GetCustomerByIdRequest { CustomerId = 1234 };
var response = service.Handle(request);  // Shouldn't this know that response is going to be CustomerResponse?

「型引数を推論できません」というメッセージが表示されます。これは一般的なジェネリック型推論の制限ですか、それともこれを機能させる方法はありますか?

4

2 に答える 2

8

制約がありますが、それはから自動的に推論できるTRequest : IRequest<TResponse>という意味ではありません。クラスは複数のインターフェイスを実装でき、複数の型を実装できることを考慮してください。独自の設計でこれを行うことはないかもしれませんが、特定のパラメーターを推測するためにクラス階層全体をたどらなければならないのは、コンパイラにとってかなり複雑です。TResponseTRequestTRequest IRequest<TResponse>

簡単に言うと、このHandleメソッドは2 つのジェネリック型パラメーター (TRequestTResponse) を取り、実際に使用できるパラメーターを 1 つだけ指定します。推論は、継承または実装する型ではなく、実際の型引数でのみ発生します。

于 2010-06-07T14:23:32.043 に答える
-1

使い方次第だと思いますが…

この場合、何か (上に挙げていないもの) が service.Handle(request); を呼び出しています。

消費するクラスが独自の宣言にジェネリック型を含まない場合、この問題が発生すると思います。

たとえば...(これは機能しません)

public class MyClass
{
     var service = new HandlingService();
     var request = new GetCustomerByIdRequest { CustomerId = 1234 };
     var response = service.Handle(request);
}

これはうまくいくはずです...(クラスはTResponseが何であるかを知る必要があります)

public class MyClass<TResponse> where TResponse : YOURTYPE
{
     var service = new HandlingService();
     var request = new GetCustomerByIdRequest { CustomerId = 1234 };
     var response = service.Handle(request);
}
于 2010-06-07T14:26:26.250 に答える