如何访问匿名linq对象的已定义属性?

时间:2014-12-07 05:46:00

标签: c# .net linq anonymous-types

我有一个答案字典对象, ans 以及这样的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()

在我的里程碑对象中,我有一个属性回答,我希望使用 milestoneid ans 对象填充数据是一个已定义的属性。但是这个代码不会编译,错误波动,说类型x不包含milestoneid的定义

因为GetSafeValue()是一个很大的方法,我不想再次使用它来填充answer属性。

Q1)如何使用 milestoneid 属性作为答案?

Q2)另外,我想使用 ans.TrygetValue() 来避免该查询中的空异常。怎么做?

感谢。

3 个答案:

答案 0 :(得分:3)

=>之后的表达式可以是一个返回新类型的完全成熟的匿名方法。因此,您可以像这样提升值:

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
    }
}

答案 1 :(得分:3)

您不能使用分配给您要返回的匿名对象的变量。意思是,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()

答案 2 :(得分:2)

您可以在导出答案(不是DRY)时重复索引器上的GetSafeValue(m.Attribute("id").Value),或者执行第二次投影以添加从初始投影派生的字段:

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的单程扩展lambda答案更好,IMO)

另外,我不确定这是否是实际代码,但请注意以下初始化是多余的

var ans = new Dictionary<string,string>();
ans = LoadAnswers();

可以简化为:

var ans = LoadAnswers();