【问题标题】:reference objects in generics c#泛型c#中的引用对象
【发布时间】:2012-03-24 18:30:51
【问题描述】:

我如何使用泛型类的 ref 作为参数并更改数据。这是我的示例代码

bool IRequestHandler.ParseRequest<T>(string request, ref T obj)
{
    var req = RequestHandlerGateway.DeserializeFromXml<OrderMessageSalesOrder>(request, "SalesOrder");

    return false;
}

我想更新 obj 中的数据。

【问题讨论】:

  • 你的代码没问题。有什么问题?
  • 在您的示例中,“T”是什么?是 OrderMessageSalesOrder 吗?

标签: c# oop generics c#-4.0 pass-by-reference


【解决方案1】:

除非您告知编译器它支持哪些附加接口,否则您对“T obj”无能为力。

例如

IRequestHandler.ParseRequest<T>(string request, T obj)
where T : IOrderInfo
{
    var req = RequestHandlerGateway.DeserializeFromXml<OrderMessageSalesOrder>(request, "SalesOrder");
    obj.OrderId = req.Id;
    return true;
}

假设 IOrderInfo 定义了 OrderId 属性,而 OrderMessageSalesOrder 提供了 Id 属性(或字段)。

只有当你打算创建一个新的 T 实例时才需要 ref:

IRequestHandler.ParseRequest<T>(string request, ref T obj)
where T : IOrderInfo, new()
{
    var req = RequestHandlerGateway.DeserializeFromXml<OrderMessageSalesOrder>(request, "SalesOrder");
    obj = new T();
    obj.OrderId = req.Id;
    return true;
}

如果你打算将反序列化的对象 req 转换为 obj,上面的答案应该足够了,但是我认为你的立场是不稳定的。

【讨论】:

    【解决方案2】:

    Ref 通常用于类型化的值。如果您的 obj 参数是引用类型(因为您将其命名为“obj”),则无需添加 ref 关键字。 要更改 obj 的值,您需要给它一个类型。一种方法是使用类型转换,例如:

    MyTyped myObj = (MyTyped)obj;
    

    设置 myObj 的值也会改变 obj 的值(因为它是一个参考)。

    此外,如果您可以找到 obj 的基类/接口,只需将代码更改为:

    bool IRequestHandler.ParseRequest<BaseClass>(string request, BaseClass obj)
    

    【讨论】:

      【解决方案3】:

      您可以将反序列化的结果转换为一个对象,然后将其转换为 T,但请确保您从 DeserializeFromXML 方法获取的对象是 T 类型

      bool IRequestHandler.ParseRequest<T>(string request, ref T obj)
      {
          var req = RequestHandlerGateway.DeserializeFromXml<OrderMessageSalesOrder>(request, "SalesOrder");
      
          obj = (T)(object)(req);    // Careful here
      
          return false;
      }
      

      由于这是一个泛型方法,因此可以为 obj 传递任何类型,但您的方法看起来像是在创建一个非常特定的类型 (OrderMessageSalesOrder)。您可能需要重新考虑为什么首先需要它是通用的

      【讨论】:

        【解决方案4】:

        如果您处理的是类而不是结构,则不需要使用ref 关键字,因为无论如何它们总是通过引用传递。您可能想改用 out 关键字,一些更改会改进它。

        bool IRequestHandler.ParseRequest<T>(string request, out T obj)
        {
            try
            {
                var req = RequestHandlerGateway.DeserializeFromXml<T>(request, "SalesOrder");
                obj = req;
                return true;
            }
            catch
            {
                obj = default(T);
                return false;
            }
        }
        

        这样你就可以如下调用它:

        OrderMessageSalesOrder salesOrder;
        
        if(handler.ParseRequest(request, out salesOrder))
        {
            // parsed successfully, salesOrder will be an instance populated with the data in the request.
        }
        else
        {
            // unable to parse, salesOrder will be null.
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-01-19
          • 1970-01-01
          • 2015-10-17
          • 1970-01-01
          • 2021-02-22
          • 1970-01-01
          • 2010-10-19
          相关资源
          最近更新 更多