Search code examples
c#extension-methodslinq-to-objectsbyref

Passing an object to a method and then calling an extenstion method on that object


I was working on a method yesterday and ran into something strange, here is dumbed down version of the code: Basically the problem is that the OrderBy applied in the Bar.PopulateList method is not persisting.


class Foo
{
    List MyObjects;

    public void PopulateMyObjects()
    {
        //Items are added to my list but the OrderBy is not persisting.
        Bar.PopulateList(MyObjects);
    }
}

class Bar
{
   public static int PopulateList(List theList)
   {
       foreach(var in WebSerbiceCall)
       {
            theList.Add(var);
       }
       // the OrderBy call only sorts 'theList' in the context of this method.
       // When I return from this method theList has been populated but the Ordering has 
       // reverted back to the order that the items were added to the list.
       theList.OrderBy(obj => obj.ID);
       return theList.Count;
   }
}

Now if I update the code and add the ref keyword as per below it all works: e.g. public static int PopulateList(ref List theList) and Bar.PopulateList(ref MyObjects);

Can anyone enlighten me? I thought objects were always passed by ref? Is it the fact that OrderBy is an extension method?

Thanks, Cian


Solution

  • The problem here is that the OrderBy call does not actually mutate theList in any way. It instead returns a new IEnumerable<object> which is ordered. Hence this is why you do not see the affects of the call outside the method, it's simply not changing the object.

    Using the OrderBy method creates a new value and hence if you want the calling function to be aware of this new value it must be returned in some manner. The most common places are in the return value or in a ref/out param.

    public static int PopulateList(ref List<object> theList) {
      ...
      theList = theList.OrderBy(obj => obj.ID).ToList();
    }