通用类型中的C#协方差

问题描述 投票:0回答:1

对于这个简单的例子,我无法绕过C#协方差,这里是我如何定义我的模型。

interface IResponse { }
interface ICommand<out TResponse> where TResponse : IResponse { }
class Response : IResponse { }
class Command<TResponse> : ICommand<TResponse> where TResponse : IResponse { }

所以我可以像这样使用它

IResponse rsp = new Response(); //Works, obviously!
ICommand<IResponse> cmdi = new Command<Response>(); //Works, but I don't need this 
Command<IResponse> cmd = new Command<Response>(); //Compile time error! :(

CommandCommand<TResponse> 甚至没有任何属性或方法的。TResponse 型。我怎样才能改变它,使其工作?

c# generics covariance contravariance mediatr
1个回答
1
投票

你的编译问题发生了,因为你声明Command只能接收TResponse,而不是IResponse。

考虑改进你的代码,而不是

class Command<TResponse>

使用

class Command<IResponse>. 

Command现在将与任何实现IResponse的TResponseXYZ类型一起工作,就像你打算的那样。为了确保Command方法能够访问TResponseXYZ类型的所有相关属性,你应该将它们发布为TResponseXYZ中的公共属性,并使用IResponse接口将它们声明为get;set;属性。工作了的例子。

interface ICommand<out TResponse> where TResponse : IResponse { }

public interface IResponse
{
    int MyField { get; set; }
}

public class TResponseA : IResponse
{
    public int MyField { get; set; }
}

public class TResponseB : IResponse
{
    public int MyField { get; set; }
}

public class Command<TResponse> : ICommand<TResponse> where TResponse : IResponse
{
    public Command(IResponse R)
    {
        // here you can access R.MyField=17 using R.MyField
    }

    public static void Test()
    {
        var rA = new TResponseA() { MyField = 17 };
        var cmdA = new Command<TResponseA>(rA);

        var rB = new TResponseB() { MyField = 17 };
        var cmdB = new Command<TResponseB>(rB);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.