Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我可以拥有/使用带有列表的字段/属性吗<;类<;T>&燃气轮机;哪里可以有什么? 原始问题_C#_Generics_Types_.net 4.5_Covariance - Fatal编程技术网

C# 我可以拥有/使用带有列表的字段/属性吗<;类<;T>&燃气轮机;哪里可以有什么? 原始问题

C# 我可以拥有/使用带有列表的字段/属性吗<;类<;T>&燃气轮机;哪里可以有什么? 原始问题,c#,generics,types,.net-4.5,covariance,C#,Generics,Types,.net 4.5,Covariance,我试图为我的web请求创建一个通用类 internal class Request<TRequest, TResponse> where TRequest : class where TResponse : class { public Uri RequestUri; public TRequest RequestItem; public TResponse ResponseItem; ... } 但是,我无法在请求列表中添加任何内容

我试图为我的web请求创建一个通用类

internal class Request<TRequest, TResponse>
    where TRequest : class
    where TResponse : class
{
    public Uri RequestUri;
    public TRequest RequestItem;
    public TResponse ResponseItem;
    ...
}
但是,我无法在请求列表中添加任何内容,因为当我尝试时:

var a = new Request<FooRequest, BarResponse>();
requests.Add(a);
这只是一个
列表
,不幸的是,我不能在类中,在方法之外声明任何类型为
var
的东西

  • 列表
    列表

    同样,不是
    列表的示例。但是让我们试试
    列表
    。。。失败:

    无法从
    My.Services.Request
    转换为
    My.Services.Request

  • 检查线程:

    这更接近我的问题

    ->有趣的是,Saeb作为我对大多数答案的评价,它与
    列表

    ->现在,布莱恩·瓦茨(Bryan Watts),在所有答案中得票最少,找到了一种有趣的方法来检索
    TRequest
    TreResponse
    。他在接口/基类中声明:

    Type DataType { get; }
    object Data { get; }
    
    这就解决了“如何检索变体”的问题

  • 第一结论 由于我需要获得变体,因此我需要实现一些
    类型RequestType
    类型ResponseType
    。这意味着
    部件将无用。这意味着我将只使用
    列表
    ,而我的Stackoverflow问题的答案是:不,你不能使用/受益于在C#中存储
    列表


    第二次编辑 显然,我没能实现布莱恩·瓦茨的解决方案。所以我不能写
    反序列化(请求)
    。所以我陷入了困境:如果我将请求添加到请求列表中,我就有了运行时类型,我不能再使用泛型方法了。我不知道通用方法这么不方便。 :(

    第二个结论 我将有一个
    列表
    ,每个
    请求
    都将为请求类型保留一个
    枚举
    ,然后我将打开此枚举并手动记录所有可能的请求调用:

    switch (@req.RequestType)
    {
        case RequestType.FirstKindOfRequest:
            await Deserialize<FirstKindOfRequest, FirstKindOfResponse>(req);
            break;
        case RequestType.SecondKindOfRequest:
            ...
    }
    
    开关(@req.RequestType)
    {
    案例RequestType.FirstKindOfRequest:
    等待反序列化(req);
    打破
    案例请求类型。第二类请求:
    ...
    }
    

    不幸的是,这是我唯一能找到的保存
    Class
    列表的方法,其中
    T
    应该是任何东西。

    我认为泛型通配符可以帮助您:

    由于这至少在不久的将来不会发生,我认为有三种选择:

    • 你可以投票,等待,并希望微软在泛型中采用通配符
    • 正如Mrida所评论的,您可以将代码转换为使用接口,然后使用C#协方差
    • 如果协方差不是一个可接受的解决方案,您可以定义一个只有非泛型功能的非泛型基类
      RequestBase
      ,并列出
      RequestBase
      edit:我想这是HenkHolterman的评论)。或者,如果您不想更改
      请求
      类,可以使用非通用功能定义非通用包装

    我认为泛型通配符可以帮助您:

    由于这至少在不久的将来不会发生,我认为有三种选择:

    • 你可以投票,等待,并希望微软在泛型中采用通配符
    • 正如Mrida所评论的,您可以将代码转换为使用接口,然后使用C#协方差
    • 如果协方差不是一个可接受的解决方案,您可以定义一个只有非泛型功能的非泛型基类
      RequestBase
      ,并列出
      RequestBase
      edit:我想这是HenkHolterman的评论)。或者,如果您不想更改
      请求
      类,可以使用非通用功能定义非通用包装

    通过提取变体
    IRequest
    接口,您可以利用接口差异:

    interface IRequest<out T, out T1>
    {
    }
    
    如果您想要一些特定于类型的行为,您仍然必须将列表的内容强制转换为更特定的类。在高流量情况下,这可能会影响性能,也可能不会影响性能

    另一个选项是存储请求的字符串内容,或将其提取到抽象基类。此抽象类的列表足以用于缓存和日志记录。您可以有如下内容:

    abstract class BaseRequest
    {
        public string RequestContent { get; protected set; }
        public string ResponseContent { get; set; }
    }
    
    class Request<TRequest, TResponse> : BaseRequest
        where TRequest : class
        where TResponse : class
    
    抽象类BaseRequest
    {
    公共字符串RequestContent{get;protected set;}
    公共字符串响应内容{get;set;}
    }
    类请求:BaseRequest
    特雷奎斯特:课堂在哪里
    在哪里响应:类
    
    你仍然可以写:

    var s = new List<BaseRequest>();
    s.Add(new Request<c1, c2>());
    
    var s=newlist();
    s、 添加(新请求());
    
    通过提取变体
    IRequest
    接口,您可以利用接口差异:

    interface IRequest<out T, out T1>
    {
    }
    
    如果您想要一些特定于类型的行为,您仍然必须将列表的内容强制转换为更特定的类。在高流量情况下,这可能会影响性能,也可能不会影响性能

    另一个选项是存储请求的字符串内容,或将其提取到抽象基类。此抽象类的列表足以用于缓存和日志记录。您可以有如下内容:

    abstract class BaseRequest
    {
        public string RequestContent { get; protected set; }
        public string ResponseContent { get; set; }
    }
    
    class Request<TRequest, TResponse> : BaseRequest
        where TRequest : class
        where TResponse : class
    
    抽象类BaseRequest
    {
    公共字符串RequestContent{get;protected set;}
    公共字符串响应内容{get;set;}
    }
    类请求:BaseRequest
    特雷奎斯特:课堂在哪里
    在哪里响应:类
    
    你仍然可以写:

    var s = new List<BaseRequest>();
    s.Add(new Request<c1, c2>());
    
    var s=newlist();
    s、 添加(新请求());
    
    这是一个典型的情况。以前也问过很多次。我看到两种方法

    ->显而易见的选择是使用非泛型基类/接口,该基类/接口可以解释所有请求类型,然后继续使用
    列表

    ->第二种方法是利用
    var s = new List<BaseRequest>();
    s.Add(new Request<c1, c2>());
    
    interface IMessage //I will call it IMessage for now
    {
        //implement whatever that make deserializing possible
    }
    
    class FooRequest : IMessage
    {
    
    }
    
    class BarResponse : IMessage
    {
    
    }
    
    interface IRequest<out TRequest, out TResponse>
        where TRequest : IMessage 
        where TResponse : IMessage 
    {
        TRequest RequestItem { get; }
        TResponse ResponseItem { get; }
        //whatever fits, but only getters for out parameter types
    }
    
    class Request<TRequest, TResponse> : IRequest<TRequest, TResponse>
        where TRequest : IMessage 
        where TResponse : IMessage 
    {
        //you can extend interface properties with setters here
    }
    
    var requests = new List<IRequest<IMessage, IMessage>>();
    var a = new Request<FooRequest, BarResponse>();
    requests.Add(a);
    foreach (var request in requests)
    {
        Deserialize(request);
    }
    
    void Deserialize<TRequest, TResponse>(IRequest<TRequest, TResponse> request)
        where TRequest : IMessage
        where TResponse : IMessage
    {
        //have access to request.RequestItem, request.ResponseItem etc
    }