Правильное использование нулевого условного оператора в LINQ при чтении XML - PullRequest
0 голосов
/ 19 октября 2019

У меня есть следующий XML-файл, который я анализирую с помощью XML-сериализатора.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Projects>
    <Global>
        <Variables>
            <Variable name="GlobalVar1" value="GV1"/>
            <Variable name="GlobalVar2" value="GV2"/>
        </Variables>
    </Global>
    <Project>
        <Variables>
            <Variable name="LocalVar1" value="LV1"/>
            <Variable name="LocalVar2" value="LV2"/>
        </Variables>
    </Project>
</Projects>

Я строю словарь переменных - пары имя-значение. Я написал следующее заявление LINQ, которое работает нормально (предположим, что у меня нет повторяющихся имен переменных в глобальной области и в области проекта):

Dictionary<String, String> varDict = Projects.Global.Variables.Select(var => new { var.name, var.value })
                .Union(Projects.Project.Variables?.Select(var => new { var.name, var.value }))
                .ToDictionary(var => var.Key, var => var.value);

Теперь у меня есть поворот - иногда либо весь тег <Global> будетотсутствует или у него не будет тега <Variables>. Аналогично, иногда тег <Variables> будет отсутствовать в теге <Project>. Например: XML-файл будет иметь вид:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Projects>
    <Project>
        <Variables>
            <Variable name="LocalVar1" value="LV1"/>
            <Variable name="LocalVar2" value="LV2"/>
        </Variables>
    </Project>
</Projects>

Я думал, что использование оператора ?. (null-conditional), как показано ниже, поможет, но при отсутствии тега <Global> следующий оператор LINQ возвращаетnull (varDict - это null):

Dictionary<String, String> varDict = Projects.Global?.Variables?.Select(var => new { var.name, var.value })
                .Union(Projects.Project.Variables?.Select(var => new { var.name, var.value }))
                .ToDictionary(var => var.Key, var => var.value);

Что я делаю не так или каково решение?

1 Ответ

1 голос
/ 19 октября 2019

Оператор ?. просто избегает создания исключения NullReferenceException. Он по-прежнему возвращает ноль.

// If Projects.Global is null:
var var1 = Projects.Global?.Variables; // Does not throw an exception, but var1 is null
var var2 = Projects.Global.Variables; // Blows up and throws a NullReferenceException

Если вы хотите, чтобы .Union() работал, когда первая часть пуста, ему нужно что-то, с чем можно поработать. Так что что-то вроде должно работать (может понадобиться немного подправить):

var globalValues = Projects.Global?.Variables?.Select(var => new KeyValuePair<string, string>(var.name, var.value)) 
        ?? new List<KeyValuePair<string, string>>();

Dictionary<String, String> varDict = globalValues
        .Union(Projects.Project.Variables?.Select(var => new KeyValuePair<string, string>(var.name, var.value)))
        .ToDictionary(var => var.Key, var => var.Value);
...