Le Quang Hoa
Le Quang Hoa

Reputation: 53

C# Pass by reference items in List<T>

When developing my simple ORM, i need to replace POCOs by its proxies, so i code some methods to process list of POCOs with my ProxyBuilder to create proxy which extends POCO and implement IEntity then reassign POCO object with new proxy, but while doing this, i face a error when casting object after reassign item in List of POCOs, it say 'Unable to cast object of type 'Order' to type 'IEntity'

I simplify my code with some classes as followings:

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 
}

Then consuming code like that

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();
}

I've known that List<> with T is class, will passed by references but in this case i dont understand why it cant, the list variable orders after process include proxies as i want but order instance is still not proxy, may be i miss something? or anyone help me change the way process List<> in my code to get this, thank in advance

Upvotes: 0

Views: 199

Answers (4)

Trevor Pilley
Trevor Pilley

Reputation: 16393

You are trying to cast the wrong thing, what you have before you call Process is the following:

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

After calling Process, you have this:

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

So in order to cast order1 as an IEntity, you need to do that via the item in the list which has been "upgraded" to an OrderProxy so you need to do this:

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

not

((IEntity)order1).ID= 1;

Upvotes: 1

qxg
qxg

Reputation: 7036

Because you replaced all items in orders with other types (OrderProxy), order1 and orders[1] are different objects now.

Try

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

If OrderProxy is like this

class OrderProxy : Order
{
    public Order Order {get;}

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

You can still access original order1 by

((OrderProxy)orders[1]).Order

Upvotes: 1

Serif Emek
Serif Emek

Reputation: 674

After calling Process you have four different objects;

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

No relationship left between order1 - orders[0] and order2 - orders[1]

What you are looking for are orders[0] and orders[1]

Upvotes: 1

Thomas
Thomas

Reputation: 2984

The problem you have is that the List itself also only has references in reality. Thus in Process you change the items[i] to no longer point to an instance of Order but instead to an instance of OrderProxy.

BUT this does not modify order1 and order2 as those two did not point to the specific items but instead to order instances which were also referenced (originally) by the items. When you changed what the items referenced the order1 and order2 are thus unaffected by this change as they did not point to items but directly to the order instances.

Edit: As you have added a second question. Your line:

((IEntity)order1).ID= 1; 

fails because IEntity is used for ProxyOrder BUT order1 is of the class Order and will always be of that class and that class is NOT deriving IEntity. Thus it cannot be automatically converted to IEntity (you would have to write a converting method if you want to do this).

Upvotes: 1

Related Questions