Defining generic interface type constraint for value and reference types
Asked Answered
K

4

6

Im having some trouble getting this generic constraint to work.

I have two interfaces below.

I want to be able to constrain the ICommandHandlers TResult type to only use types that implement ICommandResult, but ICommandResult has its own constraints that need to be supplied. ICommandResult could potentially return a value or reference type from its Result property. Am I missing something obvious? Thanks.

public interface ICommandResult<out TResult>
{
    TResult Result { get; }
}

public interface ICommandHandler<in TCommand, TResult>  where TCommand : ICommand
                                                        where TResult : ICommandResult<????>
{
    TResult Execute( TCommand command );
}
Khaki answered 18/3, 2013 at 10:1 Comment(3)
I don't see what this has to do with reference types and value typesCavalierly
The ICommandResult Result property can be either a value or reference type..Khaki
So can any other generic type unless constrained with "where T: class/struct"?Cavalierly
B
1

You could change your interface to this (which looks kind of cleaner to me):

public interface ICommandHandler<in TCommand, TResult> where TCommand : ICommand
{
    ICommandResult<TResult> Execute( TCommand command );
}

Or you could add the type parameter of ICommandResult<TResult> to your generic parameter list:

public interface ICommandHandler<in TCommand, TCommandResult, TResult> 
    where TCommand : ICommand
    where TCommandResult: ICommandResult<TResult>
{
    TCommandResult Execute( TCommand command );
}
Brinson answered 18/3, 2013 at 10:10 Comment(1)
Thanks, I think your first option is the most elegant.Khaki
F
0

You could add a 3rd generic type parameter to ICommandHandler:

public interface ICommandResult<out TResult>
{
    TResult Result { get; }
}

public interface ICommandHandler<in TCommand, TResult, TResultType>  
                                                        where TCommand : ICommand
                                                        where TResult : ICommandResult<TResultType>
{
    TResult Execute( TCommand command );
}
Fulani answered 18/3, 2013 at 10:8 Comment(0)
W
0

Hmm shouldn't your second interface look more like this?

public interface ICommandHandler<in TCommand, ICommandResult<TResult>>
    where TCommand : ICommand
{
    TResult Execute(TCommand command);
}
Writhen answered 18/3, 2013 at 10:8 Comment(3)
out there? I believe that this isn't possible!Mauk
Well this is the part I wasn't sure about. I'm currently working with .Net 3.5...I'll remove it.Writhen
You can define that a parameter is contravariant in the interface definition :DMauk
S
0

This should do it:

public interface ICommandHandler<in TCommand, out TResult>  
    where TCommand : ICommand
    where TResult : ICommandResult<TResult>
{
    TResult Execute( TCommand command );
}   
Selma answered 18/3, 2013 at 10:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.