Почему эти параметры универсального типа не могут быть выведены? - PullRequest
3 голосов
/ 07 июня 2010

Имеются следующие интерфейсы / классы:

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?

Я просто получаю сообщение "аргументы типа не могут быть выведены". Это ограничение общего вывода типа или есть способ заставить это работать?

Ответы [ 2 ]

8 голосов
/ 07 июня 2010

У вас есть ограничение TRequest : IRequest<TResponse>, но это не значит, что TResponse может быть автоматически выведено из TRequest. Учтите, что классы могут реализовывать несколько интерфейсов, а TRequest может реализовывать несколько IRequest<TResponse> типов; возможно, вы не делаете это в своем собственном проекте, но компилятору было бы довольно сложно пройти через всю иерархию классов, чтобы вывести этот конкретный параметр.

Короче говоря, метод Handle принимает два параметра универсального типа (TRequest и TResponse), и вы даете ему только один, который он действительно может использовать. Вывод происходит только для фактических аргументов типа , а не для типов, которые они наследуют или реализуют.

0 голосов
/ 07 июня 2010

Я думаю, это зависит от использования ...

В этом случае что-то (вы не перечислите это выше) вызывает service.Handle (запрос);

ЕслиКласс потребления не включает обобщенный тип в свое собственное объявление, я думаю, вы столкнетесь с этой проблемой.

Например ... (это не будет работать)

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);
}
...