在提升IEnumerable.OrderBy()之后,源列表没有排序,为什么?

时间:2012-05-04 01:09:08

标签: ienumerable

1.首先,我为IEnumerable.Add()定义了一个扩展方法,如下面的代码所示

 public static IEnumerable<T> Add<T, TKey>(this IEnumerable<T> enumerable, T value, Func<T, TKey> orderBy)
    {
        if (enumerable == null)
            return null;

        if (enumerable is IList<T>)
        {
            var list = enumerable as IList<T>;
            if (!enumerable.Contains(value))
            {
                list.Add(value);
                enumerable = enumerable.OrderBy(orderBy);
            }
        }
    }

2.然后,我提出了这样的扩展方法,当新项目被添加到列表时,根据“Date”属性对项目列表进行排序:

   itemList.Add(item, o => o.Date);

3.毕竟,似乎“itemList”没有排序。

4.我遵循扩展方法,发现“enumerable”是“enumerable = enumerable.OrderBy(orderBy)”之后的一个新实例,它已被排序,但“list”不是。

5.然后我尝试将已排序的可枚举项转换为“list = enumerable.ToList()”列表,对它们(“可枚举”和“列表”)进行了排序。

6.之后,当调用堆栈返回到“itemList.Add(item,o =&gt; o.Date);”时,“itemList”根本没有排序!!!

任何人都可以给我一些建议吗?感谢looooooooooooooooooooooooooooooooot !!

2 个答案:

答案 0 :(得分:2)

我相信你的问题是对enumerable的引用是通过值而不是引用传递的。有关这意味着什么的更多信息,请参阅Jon Skeet's article有关按值或参考传递参数的信息。简而言之,C#传递参数引用的副本,因此为参数赋值不会更改传入的对象的引用。要通过引用传递参数,请指定ref关键字,但我不要我认为这将适用于扩展方法。如果你已经开始做这项工作,我建议你按照排序顺序将这些项目插入你的List,可能要求T实现IComparable。

<强>更新

首先,看看Skeet的文章,它确实非常有用,我可能只有他的一半清晰。其次,当您将对象作为参数传递给方法时,您将传递引用的副本。这意味着您仍然可以访问对象的成员,但是,与通过复制传递值类型的方式相同,如果修改引用(即为其指定新值),则不会修改原始引用。指定ref表示您正在传递对引用的引用并更改引用(为其赋值)将影响原始对象。

答案 1 :(得分:1)

OrderBy或ToList都不会影响源列表。执行此操作时:list=enumerable.ToList()您将变量更改为指向全新的列表实例。

在我看来,这种方法做得太多了。我会继续添加和排序作为单独的操作。事实上,如果目标不是IList,这会扩展IEnumerable但是无声无效。这就是代码气味。