任何“做”/ Action LINQ运营商的计划?

时间:2009-01-24 22:04:53

标签: c# linq c#-4.0

这是一个带foreach循环的简单方法:

IEnumerable<XElement> FieldsToXElements(object instance)
{
    var fieldElements = new List<XElement>();

    foreach (var field in instance.GetType().GetFields(instance))
    {
        fieldElements.Add(new XElement(field.Name, field.GetValue(instance)));
    }

    return fieldElements;
}
有点难看。如果LINQ中有一些运算符意味着“做某事”(例如对LINQ语句中选择的每一个执行Action),那么它看起来会更好,更简洁:

IEnumerable<XElement> FieldsToXElements(object instance)
{
    var fieldElements = new List<XElement>();

    from field in instance.GetType().GetFields(instance))
    let name = field.Name
    let value = field.GetValue(instance)
    do fieldElements.Add(new XElement(name, value));

    return fieldElements;
}

我意识到这是主观的,只是我的意见。对于一个只有一行调用方法的foreach循环,我认为“do”运算符是有意义的。 但我想知道MS的任何人是否也想过同样的事情。这样的LINQ运营商是否计划在任何即将发布的版本中(例如,与C#4.0首次亮相)?

这是另一个带谓词的例子,其中虚构的do运算符会使代码看起来更干净。这样:

IEnumerable<XElement> FieldsToXElements
    (object instance, Func<FieldInfo, bool> predicate)
{
    var fieldElements = new List<XElement>();

    foreach (var field in instance.GetType().GetFields(instance).Where(predicate))
    {
        fieldElements.Add(new XElement(field.Name, field.GetValue(instance)));
    }

    return fieldElements;
}

VS。这样:

IEnumerable<XElement> FieldsToXElements
    (object instance, Func<FieldInfo, bool> predicate)
{
    var fieldElements = new List<XElement>();

    from field in instance.GetType().GetFields(instance))
    let name = field.Name
    let value = field.GetValue(instance)
    where predicate(field)
    do fieldElements.Add(new XElement(name, value));

    return fieldElements;
}

4 个答案:

答案 0 :(得分:16)

不,我不希望任何直接的语言支持(即在查询语法中)。

听起来你的意思是神话般的ForEach扩展方法;添加很简单,但Eric Lippert多次评论了无副作用的功能代码和Action<T>之间的交叉副作用。特别是,C#3.0 / .NET 3.5表达式树在side-effecs上很糟糕(使得完整的lambda支持变得棘手)。运行时端is much better in .NET 4.0,但目前尚不清楚这将使它成为C#4.0语言(lambda编译器)中的多少。

您需要的(代表版本)是:

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{   // note: omitted arg/null checks
    foreach(T item in source) { action(item); }
}

然后,您可以从任何查询中使用.ForEach(x => /* do something */)

答案 1 :(得分:3)

对于您的具体示例(填充List<XElement>),我会这样做。

IEnumerable<XElement> FieldsToXElements(object instance)
{
  List<XElement> fieldElements =
  (
    from field in instance.GetType().GetFields(instance))
    let name = field.Name
    let value = field.GetValue(instance)
    select new XElement(name, value)
  ).ToList();  //Another Option is List<T>.AddRange()
  return fieldElements;
}

另外:不要忘记List<T>已经实现.ForEach<T>(),因此要对任何Enumerable<T>使用它,这就是您需要的所有代码。

myEnumerable.ToList().ForEach( x => myAction(x) );

答案 2 :(得分:2)

我不认为这太难了或者我错过了什么......

IEnumerable<XElement> FieldsToXElements(object instance)
{
    return instance.GetType()
                   .GetFields(instance)
                   .Select( f => new XElement( f.Name,
                                               f.GetValue(instance) ) );
}

答案 3 :(得分:1)

如果您只是想在linq语句中调用函数,那么您已经可以这样做了,您可以在Let赋值中调用函数。

var qry = from e in somelist
          let errorcode = DoSomeProcessing(e)
          select e;