#c# #linq #dictionary
#c# #linq #словарь
Вопрос:
У меня есть такой объект:
class Moose
{
public int? DatabaseID; // (null if not stored)
public string Name;
}
List<moose> meese;
и я хочу сгенерировать словарь, который сопоставляет DatabaseID с именем для тех meese, которые имеют ненулевой DatabaseID.
Прямой маршрут не работает:
Dictionary<int, string> mapIdToName = meese.Where(moose => moose.DatabaseID != null).ToDictionary(moose => moose.DatabaseID, moose => moose.Name);
Я получаю
Cannot implicitly convert type 'System.Collections.Generic.Dictionary<int?, string>' to 'System.Collections.Generic.Dictionary<int, string>'
Если бы я создавал список, я мог бы сделать это:
List<int> databaseIDs = meese.Select(moose => moose.DatabaseID).OfType<int>();
Но я не могу найти ничего подобного для ToDictionary.
Сейчас я просто делаю это вручную:
Dictionary<int, string> mapIdToName = new Dictionary<int, string>();
foreach (var moose in meese)
{
if (moose.DatabaseID != null)
mapIdToName[moose.DatabaseID] = moose.Name;
}
Есть ли умный способ Linq сделать это?
Редактировать
У меня есть
#nullable enable
итак, делая это
Dictionary<int, string> mapIdToName = meese.Where(moose => moose.DatabaseID.HasValue).ToDictionary(moose => moose.DatabaseID.Value, moose => moose.Name);
не выдает ошибку, но выдает предупреждение «Тип значения с нулевым значением может быть null»
Ответ №1:
Вы можете сделать
var map = meese.Where(moose => moose.DatabaseID.HasValue).ToDictionary(moose => moose.DatabaseID!.Value, moose => moose.Name);
Обратите внимание на after , or, где вы в основном сообщаете компилятору, что я точно знаю, что это не так уж и сложно. !
DatabaseID
dammit operator
null forgiving operator
null
Комментарии:
1. О, я ненавижу оператор dammit (это похоже на проигрыш), но это может быть случай, когда это необходимо
2. Или
GetValueOrDefault
Ответ №2:
У вас почти получилось с первой попытки. При сопоставлении нулевого типа с его базовым типом вам нужно не забыть удалить значение. Это должно быть что-то вроде этого:
Dictionary<int, string> mapIdToName = meese.Where(moose => moose.DatabaseID.HasValue).ToDictionary(moose => moose.DatabaseID.Value, moose => moose.Name);
Комментарии:
1. Это становится ближе, сначала я не понимал, что включение NRT изменит ситуацию, поэтому я отредактировал свой исходный пост. Компилятор принимает это, и люди, читающие его, согласятся, что это правильно, но компилятор все еще нервничает (выдает мне предупреждение), что лось. DatabaseID.Value может быть нулевым
2. Я думаю, основная проблема заключается в том, что Where() возвращает тот же тип, который он задан, поэтому даже после Where(), который, как мы понимаем, отфильтровывает значения null, тип по-прежнему остается Dictionary<int?, string>
3. просто укажите ID.Value, например ` meese. Где(a=>a.DatabaseID.HasValue) . ToDictionary(a=>a.DatabaseID.Value, b=>b.Name )`
4. Да, это то, что предложил Гринджед — это лучше, потому что я не получаю ошибку во время компиляции, но я все равно получаю предупреждение (я обновил свой пост, чтобы включить эту информацию)