【问题标题】:Linq - How can i use "this" inside of a "select new" statementLinq - 我如何在“select new”语句中使用“this”
【发布时间】:2011-08-15 21:44:27
【问题描述】:

已编辑:

我正在递归地将一些 XML 查询到对象中。每个对象都有一个子对象列表,如果有的话,应该引用它的父对象。

示例 XML:

<object attribute1="text" attribute2="text"/>    
<object attribute1="text" attribute2="text">
    <object attribute1="text" attribute2="text">    
    <object attribute1="text" attribute2="text">    
</object>

示例 Linq:

    private static List<MyObject> ParseMyObjects(XElement node, MyObject p)
    {
        List<MyObject> myobjs = (from x in node.Elements("object")
                                select new MyObject {
                                    attribute1 = x.Attribute("attribute1 ").Value,
                                    attribute2 = x.Attribute("attribute2 ").Value,                                     
                                    subObjects = ParseMyObjects(x, this), // the "this" key word can't refer to the MyObject being created in the query, but is there some other way of doing this?
                                    parent= p
                                }).ToList();
        return myobjs;
    }

目前为了实现这一点,我正在递归遍历 MyObjects 列表,在它被查询并设置每个父级之后(排除上面的“父级”行)。

如果可能的话,我更喜欢在 Linq 查询中使用新实例化的对象的更优雅的解决方案。有什么想法吗?

编辑: 为了澄清(正如 BrokenGlass 在评论中所做的那样),代码评论所指的 this 是在查询中创建的 MyObject 的实例

【问题讨论】:

    标签: linq


    【解决方案1】:

    this 永远无法在标记为static 的方法中工作。没有实例,因为方法是静态的。

    如果可能的话,我更喜欢在 Linq 查询中使用新实例化的对象的更优雅的解决方案。有什么想法吗?

    只需使用XObject.Parent

    parent = x.Parent
    

    【讨论】:

    • 我认为this OP 指的是正在创建的MyObject 的实例,这与包含Linq 查询的方法是否为静态无关-两者都没有XObject.Parent 因为它不是 MyObject
    • @BrokenGlass:当时 OP 选择了不幸的术语,特别是因为他说“这个”关键字在这里不起作用。 this 关键字明确且仅(定义扩展方法除外)引用当前实例。
    • 不幸的是,我把问题发错了:/ 这里的对话实际上仍然适用于从 Linq 查询中创建的对象获取当前实例。
    【解决方案2】:

    如果您希望创建的MyObject 实例的Parent 成员指向实例本身,有两种方法可以实现这一点,而无需在Linq 查询之后添加迭代列表的代码:

    1) 添加一个为您设置它的构造函数,例如默认构造函数

    public MyObject() {
        this.Parent = this;
    }
    

    2) 添加一个fluent-interface风格的方法来设置父级,并在查询中调用:

    /* in class MyObject */
    public MyObject WithSelfAsParent() {
        this.Parent = this;
        return this;
    }
    
    /* updated linq query */
    List<MyObject> myobjs = (from x in node.Elements("object")
                                    select new MyObject {
                                        attribute1 = x.Attribute("attribute1 ").Value,
                                        attribute2 = x.Attribute("attribute2 ").Value,                                     
                                        subObjects = ParseMyObjects(x),                                  
    
                                    }.WithSelfAsParent()).ToList();
    

    这些是否比显式循环列表更好当然是一个品味问题。我可能会保持简单并选择循环,除非默认情况下父指针等于 this 的假设在 MyObject 类的上下文中是显而易见的,这使得在默认构造函数中设置它是自然的选择。

    【讨论】:

    • 不幸的是,我发布了错误的问题:/我已经编辑了它。至于我原来的帖子,这本来就是答案。对于那个很抱歉。如果有帮助,我投了你一票。
    • 感谢您的支持 - 我认为治疗比这里的疾病更糟糕,这不是立即可行的,但可以使用我的“fluent-interface”建议的一些变体来完成,您将函数传递给将孩子设置为回调参数。但我认为您设置父母的解决方案更好。
    • 是的,setter 解决方案比调用方法中的额外循环更好。感谢您的帮助,感谢您的友善,即使我搞砸了:)
    【解决方案3】:

    我的解决方案是利用 MyObject 上的 subObjects 属性集。

    class MyObject {
    ....
    
    private List<MyObject> _subObjects = new List<MyObject>();
    public List<MyObject> subObjects 
    {
        get { return _subObjects ; }
        set 
        { 
            _subObjects  = value;
            if(_subObjects != null)
            {
                foreach(MyObject o in _subObjects )
                {
                    o.parent = this;
                }
            }
        }
    }
    
    ....
    }
    

    如果有人知道在 Linq 语法中引用新创建/选择的对象的方法,我会将您的答案标记为正确的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多