【问题标题】:How to format complex chained Linq statements for readibility?如何格式化复杂的链式 Linq 语句以提高可读性?
【发布时间】:2011-02-28 23:11:13
【问题描述】:

我有一些这样的代码:

var effects = xElement.Elements ( "Effects" ).Elements ( "Effect" ).Select (
    e => new Effect (
        ( EffectType ) Enum.Parse ( typeof ( EffectType ), ( string ) e.Elements ( "Type" ).FirstOrDefault ( ) ),
        e.Elements ( "Options" ).Any ( )
            ? e.Elements ( "Options" ).Select ( o => ( object ) o.Elements ( "Option" ).Select ( n => n.Value ).First ( ) )
            : null ) )
            .ToList ( );

但目前这看起来不可读,我不确定应该在哪里添加新行和/或缩进以提高可读性。

有什么建议可以用来制作一致、可读的 linq 块?

【问题讨论】:

  • 这是我的评论;不要使用 LINQ,因为它会更清楚地显示为遍历每个元素的简单循环,获取属性,然后将新对象添加到列表中。
  • 谢谢,可以举个例子。我不确定您如何以相同的方式使用循环来实现这一点。

标签: c# .net linq coding-style


【解决方案1】:

完全主观的问题,甚至不知道我为什么要回答它,但这里是对我来说更具可读性的问题

var effects = xElement
    .Elements("Effects")
    .Elements("Effect")
    .Select(e => 
        new Effect(
            (EffectType)Enum.Parse(
                typeof(EffectType), 
                (string)e.Elements("Type").FirstOrDefault()
            ),
            e.Elements("Options").Any() 
                ? e.Elements("Options").Select(
                    o => o.Elements("Option").Select(n => n.Value).First()
                )
                : null
        ) 
    )
    .ToList();

或者如果您更喜欢查询语法:

var effects = 
    from e in xElement.Elements("Effects").Elements("Effect")
    let effectType = 
        (EffectType)Enum.Parse(
            typeof(EffectType), 
            (string)e.Elements("Type").FirstOrDefault()
        )
    let options = 
        e.Elements("Options").Any() 
            ? e.Elements("Options").Select(
                  o => o.Elements("Option").Select(n => n.Value).First()
            )
            : null
    select new Effect(effectType, options);

【讨论】:

  • 这就是我会写的,几乎完全一样
  • 这看起来确实不错,但现在我在想为什么它为 .Elements("Effects")、.Elements("Effect") 使用新行,而不是 Elements("Options")、Elements (“选项”)?
  • 谢谢达林,我实际上是在询问 e.Elements("Options").Any() 和 o => o.Elements("Option") 行,我假设他们会有新的e 和 .Elements("Options") 和/或 .Any() 等的行。这有意义吗?
【解决方案2】:

我更喜欢名称清晰的小函数。像这样的:

    public void Parse()
    {
        //XElement xElement = blah...

        var elements = xElement.Elements("Effects").Elements("Effect");
        var converted = elements.Select(ConvertToEffect);
    }

    private static Effect ConvertToEffect(XElement e)
    {
        var value = ConvertEnum((string) e.Elements("Type").FirstOrDefault());
        var option = GetOption(e.Elements("Options"));

        return new Effect(value, option);
    }

    private static EffectType ConvertEnum(string value)
    {
        return (EffectType)Enum.Parse(typeof(EffectType), value);
    }

    private static IEnumerable<object> GetOption(IEnumerable<XElement> e)
    {
        var any = e.Elements("Options").Any();
        if (any)
        {
            return e.Elements("Options").Select(o => (object) o.Elements("Option").Select(n => n.Value).First());
        }

        return null;
    }

【讨论】:

    【解决方案3】:

    改用查询表达式。我认为它会更具可读性。

    【讨论】:

    • 谢谢,您能否举个例子,因为我无法编写最优雅的查询语法。
    【解决方案4】:

    我想我会像这样格式化它:

    var effects =
      xElement.Elements("Effects").Elements("Effect")
      .Select (
        e => new Effect(
          (EffectType)Enum.Parse(
            typeof(EffectType),
            (string)e.Elements("Type").FirstOrDefault()
          ),
          e.Elements("Options").Any() ?
            e.Elements("Options")
            .Select(o => (object)o.Elements("Option")
            .Select(n => n.Value).First())
            : null
        )
      )
      .ToList ();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-12
      • 2020-11-18
      • 2015-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多