Reputation: 6780
I've an answers dictionary object, ans and a LINQ query like this:
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()
Inside my milestones object, I've a property answer where I want to populate the data from ans object using milestoneid which is an already defined property. But this code won't compile, with error squiggly saying that type x does not contain a definition for milestoneid.
Since, GetSafeValue() is a huge method, I don't want to use it again to populate the answer property.
Q1) How can I use the milestoneid property for my answer ?
Q2) Also, I want to use ans.TrygetValue() to avoid null exceptions within that query. How to do that ?
Thanks.
Upvotes: 1
Views: 219
Reputation: 107237
You could repeat the GetSafeValue(m.Attribute("id").Value)
on the indexer when deriving answer (which isn't DRY), or instead, do a second projection to add fields derived from the initial projection:
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's single-pass extended lambda answer is better, IMO)
Also, I'm not sure if this is actual code, but note that the below initialization is redundant
var ans = new Dictionary<string,string>();
ans = LoadAnswers();
Is reducable to just:
var ans = LoadAnswers();
Upvotes: 2
Reputation: 1827
You are not allowed to use a variable that's being assigned to the anon object you are returning. Meaning, milestoneid is a property of the new object, not a local variable. You could do this: ans[GetSafeValue(m.Attribute("id").Value)]
. That is adding some unfortunate duplication though, I would recommend something more like this:
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()
As for the second question, TryGetValue returns a bool, and has an out param.
object answer; // the type should be whatever you are expecting.
ans.TryGetValue(id, out answer);
Maybe something like:
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()
Upvotes: 3
Reputation: 7638
The expression after the =>
can be a full fledged anonymous method that returns the new type. Hence you can hoist the values like so:
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
}
}
Upvotes: 3