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 !!
答案 0 :(得分:2)
我相信你的问题是对enumerable的引用是通过值而不是引用传递的。有关这意味着什么的更多信息,请参阅Jon Skeet's article有关按值或参考传递参数的信息。简而言之,C#传递参数引用的副本,因此为参数赋值不会更改传入的对象的引用。要通过引用传递参数,请指定ref
关键字,但我不要我认为这将适用于扩展方法。如果你已经开始做这项工作,我建议你按照排序顺序将这些项目插入你的List,可能要求T实现IComparable。
<强>更新强>
首先,看看Skeet的文章,它确实非常有用,我可能只有他的一半清晰。其次,当您将对象作为参数传递给方法时,您将传递引用的副本。这意味着您仍然可以访问对象的成员,但是,与通过复制传递值类型的方式相同,如果修改引用(即为其指定新值),则不会修改原始引用。指定ref
表示您正在传递对引用的引用并更改引用(为其赋值)将影响原始对象。
答案 1 :(得分:1)
OrderBy或ToList都不会影响源列表。执行此操作时:list=enumerable.ToList()
您将变量更改为指向全新的列表实例。
在我看来,这种方法做得太多了。我会继续添加和排序作为单独的操作。事实上,如果目标不是IList,这会扩展IEnumerable但是无声无效。这就是代码气味。