问题:
你希望能够反转数据项的有序列表中的内容,并且还能够同时以数组和列表方式访问它们,就像使用SortedList 和泛型类 SortedList<T> 那样。SortedList 和SortedList<T> 都没有提供除重加载列表之外完成该任务的直接方式。
解决方案:
使用LINQ to Object查询SortedList<T>,并对列表中的信息应用降序排序。在实例化一个键为int、值为string的SortedList<TKey,TValue>之后,把一系列无序的数字以及它们的文本表示插入列表中。然后会显示这些数据项。
SortedList<int, string> data = new SortedList<int, string>()
{
[2] = "two",
[5] = "five",
[3] = "three",
[1] = "one"
};
foreach (KeyValuePair<int, string> kvp in data)
{
Console.WriteLine($"\t {kvp.Key}\t{kvp.Value}");
}
然后以升序(默认情况)排序的方式显示列表的输出。
1 one
2 two
3 three
5 five
现在,通过使用LINQ to Object创建一个查询并把orderby子句设置为descending来反转排序顺序。然后从查询结果集中显示结果:
// 降序排序查询
var query = from d in data
orderby d.Key descending
select d;
foreach (KeyValuePair<int, string> kvp in query)
{
Console.WriteLine($"\t {kvp.Key}\t{kvp.Value}");
}
这一次结果以降序排序显示:
5 five
3 three
2 two
1 one
当把新的数据项添加到列表中时,将以升序的排序方式添加它,但是通过在添加了所有数据项之后再查询列表,可以使列表的排序方式保持不变。
data.Add(4, "four");
// 降序排序重新查询
query = from d in data
orderby d.Key descending
select d;
foreach (KeyValuePair<int, string> kvp in query)
{
Console.WriteLine($"\t {kvp.Key}\t{kvp.Value}");
}
Console.WriteLine("");
// 访问原始列表以升序方式显示
foreach (KeyValuePair<int, string> kvp in data)
{
Console.WriteLine($"\t {kvp.Key}\t{kvp.Value}");
}
然后可以在以升序或降序排序的输出中看到新添加的数据项:
5 five
4 four
3 three
2 two
1 one
1 one
2 two
3 three
4 four
5 five
讨论:
SortedList 融合了数组和列表的语法,允许以任何一种方式来访问数据,用起来很方便。可以以键值对或者直接通过索引访问数据,并且不允许添加重复的键。此外,引用或可空类型的值可以是null,但是键不能是null。可以使用foreach 循环迭代访问数据项,其返回类型是KeyValuePair。在访问SortedList<T> 的元素时,只能读取它们。通常的迭代器语法禁止在读取列表中的元素时更新或删除它们,因为这将使迭代器无效。
查询子句中的orderby 子句将导致查询的结果集以升序(默认)或降序排序。这种排序是使用针对元素类型的默认比较器完成的,因此对于自定义类型的元素,可以通过重写Equals 方法来影响它。可以为orderby 子句指定多个键,因为它具有嵌套排序的作用,比如先按“last name”排序,再按“first name”排序。
参考:
MSDN 文档中的“SortedList”“泛型KeyValuePair 结构”和“泛型SortedList”主题。