Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any plans for "do"/Action LINQ operator?

Tags:

c#

linq

c#-4.0

Here's a simple method with a foreach loop:

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

Kind of ugly. If there were some operator in LINQ that mean "do something" (e.g. perform an Action for each selected in the LINQ statement), it would look nicer, more terse:

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

I realize that's subjective, and just my opinion. For a foreach loop that has one line that simply invokes a method, a "do" operator makes sense, in my opinion. But I'm wondering if anyone at MS has thought the same thing. Is such LINQ operator planned in any upcoming releases (e.g. alongside the C# 4.0 debut)?

Here's another example, with a predicate, where the fictitious do operator would really make the code look cleaner. This:

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. this:

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;
}
like image 769
core Avatar asked Jan 24 '09 22:01

core


People also ask

Which is better Entity Framework or LINQ to SQL?

First off, if you're starting a new project, use Entity Framework ("EF") instead of Linq to SQL because it now generates far better SQL (more like Linq to SQL does) and is easier to maintain ("L2S").

What does any do in LINQ?

The Any operator is used to check whether any element in the sequence or collection satisfy the given condition. If one or more element satisfies the given condition, then it will return true. If any element does not satisfy the given condition, then it will return false.

Is LINQ multithreaded?

By default, only one thread is used to execute a LINQ query. Parallel LINQ (PLINQ) is an easy way to enable multiple threads to execute a query. To see it in action, we will start with some code that only uses a single thread to double 200 million integers.

Can we use LINQ with Entity Framework?

LINQ to Entities provides Language-Integrated Query (LINQ) support that enables developers to write queries against the Entity Framework conceptual model using Visual Basic or Visual C#. Queries against the Entity Framework are represented by command tree queries, which execute against the object context.


2 Answers

No, I don't expect any direct language suport (i.e. inside the query syntax) any time soon.

It sounds like you mean the mythical ForEach extension method; trivial to add, but Eric Lippert has commented numerous times about the cross between side-effect-free functional code and Action<T> with side-effects. In particular, C# 3.0 / .NET 3.5 expression trees are lousy at side-effecs (making full lambda support tricky). The runtime side is much better in .NET 4.0, but it is unclear at the moment how much of this will make it into the language (lambda compiler) in C# 4.0.

All you need (for delegate version) is:

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

Then from any query you can simply use .ForEach(x => /* do something */).

like image 92
Marc Gravell Avatar answered Sep 29 '22 00:09

Marc Gravell


For your specific example (populating a List<XElement>), I'd do it this way.

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

Also: Don't forget that List<T> already implements .ForEach<T>(), so to use it against any Enumerable<T>, this is all the code you need.

myEnumerable.ToList().ForEach( x => myAction(x) );
like image 36
Amy B Avatar answered Sep 29 '22 01:09

Amy B