1

I'm scratching my head to try and make this work, but I'm not sure how to tell the compiler about the types in a way as to avoid explicitly stating them.

Consider a simple interface like this:

interface ICommand<TResult> { }

And a sample implementation:

class SomeCommand : ICommand<int> { }

Now, we have a generic processor interface:

interface ICommandProcessor
{
    TResult Process<TCommand, TResult>(TCommand command)
        where TCommand : ICommand<TResult>;
}

When I try to use this interface with a concrete command object, I still get a type inference error from the compiler:

Error CS0411 The type arguments for method 'ICommandProcessor.Process(TCommand)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

class Consumer
{
    private readonly ICommandProcessor _commandProcessor;

    Consumer(ICommandProcessor commandProcessor)
    {
        _commandProcessor = commandProcessor;
    }

    public int SomeMethod()
    {
        return _commandProcessor.Process(new SomeCommand());
    }
}

Why is the compiler unable to infer the types in this case, and how can I change the code to enable inference if at all possible?

julealgon
  • 7,072
  • 3
  • 32
  • 77
  • Why do you even need to do that? There's no point in knowing that type. I'm not even sure if the phrase "knowing that type" makes any sense in this scenario. – cwharris Jun 15 '18 at 22:38
  • 1
    Why not use `TArg Process(ICommand command)` in `ICommandProcessor` instead? It seems like you are over complicating your generic arguments and then restricting them to specific types. – Ron Beyer Jun 15 '18 at 23:16
  • @RonBeyer's suggestion will work up until you run into a `SomeOtherCommand : ICommand, ICommand`, which is going to be a problem with this approach no matter how you come at it. – Jonathon Chase Jun 15 '18 at 23:23

1 Answers1

1

I think this is where you're getting caught up:

public int SomeMethod()
{
    return _commandProcessor.Process(new SomeCommand());
}

It sounds like you're wondering why C# doesn't infer that the return type of Process is int. Logically, int is the only return type it is capable of producing. And yet, Process doesn't need to know the concrete type of its argument to achieve this.

interface ICommandProcessor
{
    TResult Process<TResult>(ICommand<TResult> command);
}

This is sufficient to infer the return type of Process, and Process has no use for knowing the concrete type implementing ICommand, technically speaking, Process can't know the concrete type unless you specify it in a type constraint (where TCommand : SomeCommand), which isn't useful anyways.

It just doesn't make sense to infer the type of Command, so the problem you're presenting doesn't require a solution. It just needs to be avoided entirely.

cwharris
  • 17,835
  • 4
  • 44
  • 64