0

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.然后,我提出了这样的扩展方法,以便在将新项目添加到列表时根据“日期”属性对项目列表进行排序:

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

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

4.我按照扩展方法,发现“enumerable”是在“enumerable = enumerable.OrderBy(orderBy)”之后的一个新实例,并且被排序了,而“list”没有。

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

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

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

4

2 回答 2

2

我相信您的问题是对 enumerable 的引用是通过值而不是通过引用传递的。有关这意味着什么的更多信息,请参阅Jon Skeet 关于按值或参考传递参数的文章。简而言之,C# 传递参数引用的副本,因此为参数分配新值不会更改传入对象的引用。要通过引用传递参数,请指定ref关键字,但我认为这不会使用扩展方法。如果您对完成这项工作已经下定决心,我建议您按排序顺序将项目插入到您的列表中,可能需要 T 实现 IComparable。

更新:

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

于 2012-05-04T01:24:22.630 回答
1

OrderBy 或 ToList 都不会影响源列表。当您这样做时:list=enumerable.ToList()您将变量更改为指向一个全新的列表实例。

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

于 2012-05-04T01:25:21.287 回答