0

So, I have the following code:

public interface ICommand<out TResponse> {...}

public interface IOperationResult {...}

public interface IOperationResult<out T> : IOperationResult {...}

public struct OperationResult : IOperationResult {...}

public struct OperationResult<T> : IOperationResult<T> {...}

public sealed class AuthorizationBehavior<TRequest, TResponse>
    where TRequest : class, ICommand<IOperationResult>
    where TResponse : IOperationResult {...}

public class CreateCommand : ICommand<OperationResult<string>>{...}

Now, if I try do do a new AuthorizationBehavior<CreateCommand, OperationResult<string>>() the compiler errors "The type 'CreateCommand' cannot be used as type parameter 'TRequest' in the generic type or method 'AuthorizationBehavior'. There is no implicit reference conversion..."

But, if instead of structs I make both OperationResult a class, everything is fine. Why?

I would like to maintain the structs as those results are usually very short lived and small, but also I can't change the constrains on AuthorizationBehavior to use the concrete type instead of the interface (because that constrain let me use both types of OperationResult)

CheloXL
  • 167
  • 2
  • 9
  • @EhsanSajjad did you even try? Copy/paste the above code (minus dots) simply don't compile. – CheloXL Feb 21 '18 at 18:47
  • @EhsanSajjad The only thing you need to do to reproduce the problem is remove the `...` that the OP added all over the place to make the code not compile for other reasons. Removing those results in it reproducing the problem as described. – Servy Feb 21 '18 at 18:48
  • @EhsanSajjad You didn't copy all of the code, specifically the line that the OP said was the one that doesn't compile. – Servy Feb 21 '18 at 18:49

1 Answers1

0

Do the following:

public sealed class AuthorizationBehavior<TRequest, TResponse>
        where TRequest : class, ICommand<TResponse>
        where TResponse : IOperationResult
    { }

This is because the way ICommand was declared:

public interface ICommand<out TResponse> { } 

That is with TResponse as type and not the specific IOperationResult. Recall that CreateCommand is derived from ICommand!

Edit: If you need that TResponse will implement IOperationResult then add the following restriction:

public interface ICommand<out TResponse> where TResponse : IOperationResult {}
Ilan
  • 624
  • 6
  • 11
  • I *need* that constrain so I can be sure that I have access to specific methods of the request inside the AuthorizationBehavior. – CheloXL Feb 21 '18 at 18:50
  • Then restrict ICommand the way I did in the edit above. But actually I did not understand what kind access you need. – Ilan Feb 21 '18 at 18:55
  • Adding the constrain didn't help. Same error. IOperationResult has some properties that I need to access inside my behavior. The above is over simplified to get to the point. – CheloXL Feb 21 '18 at 19:01