У меня есть словарный словарь, анс и запрос LINQ:
ans = new Dictionary<string,string>();
ans = LoadAnswers();
var milestones = LoadMilestones(session).Select(
m => new
{
milestoneid = GetSafeValue(m.Attribute("id").Value),
duedate = GetSafeValue(m.XPathValue("duedate")),
answer = ans[milestoneid]
}).ToArray()
Внутри объекта моей вехи у меня есть ответ свойства, где я хочу заполнить данные из объекта ans, используя milestoneid, который является уже определенным свойством. Но этот код не будет компилироваться, при этом ошибка squiggly говорит, что тип x не содержит определения для milestoneid.
Поскольку GetSafeValue() является огромным методом, я не хочу использовать его снова, чтобы заполнить свойство answer.
Q1) Как я могу использовать свойство milestoneid для моего ответа?
Q2) Кроме того, я хочу использовать ans.TrygetValue(), чтобы избежать нулевых исключений в этом запросе. Как это сделать?
Благодарю.
Выражение после =>
может быть полнофункциональным анонимным методом, который возвращает новый тип. Следовательно, вы можете поднять значения так:
m => {
var id = GetSafeValue(m.Attribute("id").Value);
string answer;
return new {
milestoneid = id,
duedate = GetSafeValue(m.XPathValue("duedate")),
answer = ans.TryGetValue(id, out answer) ? answer : null
}
}
Вам не разрешено использовать переменную, которая назначается объекту anon, который вы возвращаете. Значение, milestoneid является свойством нового объекта, а не локальной переменной. Вы можете сделать это: ans[GetSafeValue(m.Attribute("id").Value)]
. Это добавляет некоторые неудачные дублирования, хотя я бы рекомендовал нечто большее:
var milestones = LoadMilestones(session).Select(
m => {
var id = GetSafeValue(m.Attribute("id").Value);
return new
{
milestoneid = id,
duedate = GetSafeValue(m.XPathValue("duedate")),
answer = loadStudentResponse ? null : ans[id]]
};
}).ToArray()
Что касается второго вопроса, TryGetValue возвращает bool и имеет параметр out.
object answer; // the type should be whatever you are expecting.
ans.TryGetValue(id, out answer);
Может быть, что-то вроде:
var milestones = LoadMilestones(session).Select(
m => {
var id = GetSafeValue(m.Attribute("id").Value);
object answer; // the type should be whatever you are expecting.
ans.TryGetValue(id, out answer);
return new
{
milestoneid = id,
duedate = GetSafeValue(m.XPathValue("duedate")),
answer = answer
};
}).ToArray()
Вы можете повторить GetSafeValue(m.Attribute("id").Value)
в индексере при получении ответа (который не является DRY) или вместо этого сделать второй прогон, чтобы добавить поля, полученные из начальной проекции:
var milestones = LoadMilestones(session)
.Select(m => new
{
milestoneid = GetSafeValue(m.Attribute("id").Value),
duedate = GetSafeValue(m.XPathValue("duedate")),
})
.Select(x => new
{
x.milestoneid,
x.duedate,
answer = ans[x.milestoneid]
})
.ToArray();
(neouser99 однопроходный расширенный лямбда-ответ лучше, ИМО)
Кроме того, я не уверен, что это фактический код, но обратите внимание, что приведенная ниже инициализация избыточна
var ans = new Dictionary<string,string>();
ans = LoadAnswers();
Допускается сводить к простому:
var ans = LoadAnswers();