Если я применяю метод расширения LINQ Take
к SortedList<int, int>
, как мне преобразовать результат в новый SortedList<int, int>
?
Из полученной ошибки во время выполнения, результатом метода Take является EnumerablePartition
который не может быть приведен к SortedList<int, int>
Основной метод в консольном приложении компилируется нормально, но выдает ошибку во время выполнения при приведении результата list.Take(2) к SortedList
static void Main(string[] args)
{
Console.WriteLine("List");
var list = new SortedList<int, int>();
list.Add(2, 10);
list.Add(8, 9);
list.Add(3, 15);
foreach (KeyValuePair<int, int> item in list){
Console.WriteLine(item.Value);
};
Console.WriteLine("Short List");
var shortlist = (SortedList<int, int>)list.Take(2);
foreach (KeyValuePair<int, int> item in shortlist)
{
Console.WriteLine(item.Value);
};
Console.Read();
}
Я ожидал, что результатом метода Take
будет новый SortedList<int, int>
или хотя бы то, что можно будет привести его к SortedList<int, int>
учитывая, что это оригинальный тип.
Вот ошибка времени выполнения, которую я получаю:
Unable to cast object of type 'EnumerablePartition'1[System.Collections.Generic.KeyValuePair'2[System.Int32,System.Int32]]' to type 'System.Collections.Generic.SortedList'2[System.Int32,System.Int32]'
РЕДАКТИРОВАТЬ:
Я относительно новичок в LINQ и Generics, но благодаря полученным отличным ответам я создал новый метод расширения для удобства чтения:
static class Extensions {
public static SortedList<TKey, TValue> ToSortedList<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> collection)
{
var dictionary = collection.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
return new SortedList<TKey, TValue>(dictionary);
}
}
Теперь, чтобы создать мой список:
var shortlist = list.Take(2).ToSortedList();
Я думал, что что-то подобное может быть уже доступно!
учитывая, что это оригинальный тип
Да, но Take()
является методом расширения в IEnumerable<T>
, а SortedList<TKey, TValue>
реализует IEnumerable<KeyValuePair<TKey, TValue>>
.
Таким образом, тип вы получаете назад от Take()
не должен иметь никакого отношения к источнику вы называете его - она просто возвращает реализацию IEnumerable<T>
, где T
является тот же тип T
от IEnumerable<T>
Вы называете это.
Вместо этого создайте новый список, используя раздел и соответствующий ему конструктор:
var shortlist = new SortedList<int, int>(list.Take(2).ToDictionary(kvp => kvp.Key, kvp => kvp.Value));
Я ожидал бы, что результатом метода Take будет новый SortedList или, по крайней мере, будет возможно приведение к SortedList, учитывая, что это оригинальный тип.
Ну, это не совсем так. Если вы Take(2)
из пакета конфет, у вас есть две конфеты. У вас нет волшебной сумки с двумя конфетами просто потому, что в сумке были оригинальные конфеты.
Технически говоря, метод Take
принимает IEnumerable<>
любого типа и возвращает IEnumerable<>
того же типа. Информация исходного типа контейнера теряется в процессе.
Очевидно, что, как в нашем примере со сладостями, если вы хотите иметь крошечные пакеты по две конфеты в каждой из вашей большой сумки, никто не помешает вам переупаковать их. Тоже самое. Если вам нужен отсортированный список, создайте новый отсортированный список из результата. Но это руководство.
Вы можете использовать конструктор SortedList
var sortedList = new SortedList<int, int>(list.Take(2).ToDictionary(x => x.Key, x => x.Value));
Take
не возвращает SortedList
поэтому вам нужно создать новый так или иначе:
var shortList = new SortedList<int, int>();
foreach (var x in list.Take(2))
shortList.Add(x.Key, x.Value);
IEnumerable<>
которые мне придется использовать. Благодарю.