C# Pass by reference items in List<T>

本文关键字:lt gt List in Pass by reference items | 更新日期: 2023-09-27 18:19:56

在开发我的简单ORM时,我需要用它的代理替换POCO,所以我用ProxyBuilder编写了一些方法来处理POCO列表,以创建扩展POCO并实现IEntity的代理,然后用新的代理重新分配POCO对象,但在这样做的时候,我在POCO列表中重新分配项目后铸造对象时遇到了错误,它说"无法将Order类型的对象强制转换为IEntity类型的"

我用以下一些类来简化我的代码:

public class Order
{
    public string Code { get; set; }
    public string Description { get; set; }
    public DateTime Date { get; set; }
    public decimal Total { get; set; }
}
interface IEntity
{
    public long ID;
}
public class OrderProxy : Order, IEntity
{
    // some functions of a proxy 
}

然后消费类似的代码

public void Run()
{
    Order order1 = new Order() { .... }; 
    Order order2 = new Order() { .... };
    List<Order> orders = new List<Order>();
    items.Add(order1);
    items.Add(order2);
    Process<Order>(orders);
    // ERROR occured here 'Unable to cast object of type 'Order' to type 'IEntity' 
    ((IEntity)order1).ID= 1; 
}
public void Process<T>(List<T> items)
{
    for (int i = 0; i < items.Count; i++)
    {
        items[i] = (T)CreateProxy();
    }
}
private object CreateProxy(object obj)
{
    // my ProxyBuilder will create new instance of OrderProxy depend on passed POCO parameter then return it
    return new OrderProxy();
}

我知道List<>对于T是类,将通过引用传递,但在这种情况下,我不明白为什么它不能,处理后的列表变量orders包括我想要的代理,但order实例仍然不是代理,我可能错过了什么吗?或者任何人帮助我更改处理List<>的方式在我的代码中,提前感谢

C# Pass by reference items in List<T>

问题是List本身实际上也只有引用。因此,在Process中,您将item[i]更改为不再指向Order的实例,而是指向OrderProxy的实例。

但这不会修改order1和order2,因为这两个没有指向特定的项目,而是指向项目(最初)引用的订单实例。更改引用的项目时,order1和order2不受此更改的影响,因为它们不指向项目,而是直接指向订单实例。

编辑:正如你补充的第二个问题。您的线路:

((IEntity)order1).ID= 1; 

失败,因为IEntity用于ProxyOrder,但是order1属于Order类,并且将始终属于该类,并且该类不是派生IEntity的。因此,它不能自动转换为IEntity(如果你想这样做,你必须编写一个转换方法)。

调用Process后,您有四个不同的对象;

order1, order2, orders[0], orders[1]

订单1-订单[0]和订单2-订单[1]之间没有关系

您要查找的是订单[0]和订单[1]

因为您用其他类型(OrderProxy)替换了订单中的所有项目,所以order1orders[1]现在是不同的对象。

尝试

((IEntity)orders[1]).ID = 1;

如果OrderProxy像这个

class OrderProxy : Order
{
    public Order Order {get;}
    public OrderProxy(Order o)
    {
         this.Order = o;
    }
}

您仍然可以通过访问原始订单1

((OrderProxy)orders[1]).Order

您试图抛出错误的东西,在调用Process之前,您有以下内容:

Order order1
Order order2
List<Order> orders
Order orders[0]
Order orders[1]

调用Process后,您将得到以下信息:

Order order1
Order order2
List<Order> orders
OrderProxy orders[0]
OrderProxy orders[1]

因此,为了将order1转换为IEntity,您需要通过列表中已"升级"为OrderProxy的项目来执行此操作,因此您需要执行以下操作:

((IEntity)orders[0]).ID= 1;

不是

((IEntity)order1).ID= 1;