2010-12-02 130 views
0

我昨天正在研究一个方法,并遇到了一些奇怪的问题,这里是代码的笨拙版本:基本上问题是OrderBy应用于Bar.PopulateList方法不是持久的。将对象传递给方法,然后调用该对象的扩展方法


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

现在,如果我更新代码,并添加ref关键字按下面的所有作品: 例如public static int PopulateList(ref List List) and Bar.PopulateList(ref MyObjects);

任何人都可以启发我吗?我以为对象总是被ref引用? OrderBy是一种扩展方法吗?

感谢,慈安

回答

4

这里的问题是,OrderBy呼叫实际上并不以任何方式变异theList。它会返回一个新的订购的IEnumerable<object>。因此,这就是为什么你没有看到方法外的调用的影响,它不会改变对象。

使用OrderBy方法会创建一个新值,因此如果您希望调用函数知道这个新值,它必须以某种方式返回。最常见的地方是返回值或参数ref/out

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

尝试:

return theList.OrderBy(obj => obj.ID).Count; 

(我要添加一个交代,但@jaredPar解释它)

+0

有序枚举是否与未排序列表具有相同数量的元素? – dtb 2010-12-02 00:29:28

+0

OrderBy上面有代码:theList.Add(var);所以我不认为这是可以假设的。 – jwwishart 2010-12-02 00:33:30

+0

但OrderBy不添加或删除任何元素,所以`theList.OrderBy(obj => obj.ID).Count()`应该等于`theList.Count`,否? – dtb 2010-12-02 01:05:19

1

C#通过值传递参数,它只是参考类型的值是指向它的内存位置的指针。你遇到的问题是这一行:

theList.OrderBy(obj => obj.ID); 

你不是分配结果:

theList = thisList.OrderBy(obj => obj.ID).ToList(); 
0

如果您不使用ref关键字,则传递的参数是对同一对象的新引用。从某种意义上说,它是“通过引用传递”的,但你必须有点不同地思考。

其他答案都是正确的,OrderBy没有执行到位,而是返回一个有序集合。但是,如果将参数设置为结果,则将参数(参考)的值更改为指向新集合,而不是更改底层对象本身。

例如,

theList = thisList.OrderBy(obj => obj.ID).ToList(); 

需要theList,订单,然后创建一个新的列表。然后,将theList(它是对列表的引用)的值更改为指向新创建(排序)的列表。在此方法之外创建的原始引用仍然指向原始无序列表。

原因是,只要你打电话给.ToList()你实际上会创建一个新的列表。当您使用ref关键字时,您将包含引用的实际变量传递给列表,而不是创建对同一列表的新引用。