开发者

LINQ query to select based on property

IEnumerable<MyClass> objects = ...
foreach(MyClass obj in objects)
{
  if(obj.someProperty != null)
    SomeFunction(obj.someProperty);
}

I get the feeling I can write a smug LINQ version using a lambda but all my C# experience is 'classical' i.e more Java-like and all t开发者_如何学运维his Linq stuff confuses me.

What would it look like, and is it worth doing, or is this kind of Linq usage just seen as showing off "look I know Linq!"


LINQ itself doesn't contain anything for this - I'd would use a normal foreach loop:

foreach (var value in objects.Select(x => x.someProperty)
                             .Where(y => y != null))
{
    SomeFunction(value);
}

Or if you want a query expression version:

var query = from obj in objects
            let value = obj.SomeProperty
            where value != null
            select value;
foreach (var value in query)
{
    SomeFunction(value);
}

(I prefer the first version, personally.)

Note that I've performed the selection before the filtering to avoid calling the property twice unnecessarily. It's not for performance reasons so much as I didn't like the redundancy :)

While you can use ToList() and call ForEach() on that, I prefer to use a straight foreach loop, as per Eric's explanation. Basically SomeFunction must incur a side-effect to be useful, and LINQ is designed with side-effect-free functions in mind.


objects.where(i => i.someProperty != null)
    .ToList()
    .ForEach(i=> SomeFunction(i.someProperty))


Although it can be done with Linq, sometimes its not always necessary. Sometimes you lose readability of your code. For your particular example, I'd leave it alone.


One option is to use the pattern outlined in the book Linq In Action which uses an extension method to add a ForEach operator to IEnumerable<>

From the book:

public static void ForEach<T> (this IEnumerable<T> source, Action<T> func)
{
   foreach (var item in source)
      func(item)
}

Then you can use that like this:

(from foo in fooList 
  where foo.Name.Contains("bar")
  select foo)
  .ForEach(foo => Console.WriteLine(foo.Name));


LINQ is used to create a result, so if you use it to call SomeFunction for each found item, you would be using a side effect of the code to do the main work. Things like that makes the code harder to maintain.

You can use it to filter out the non-null values, though:

foreach(MyClass obj in objects.Where(o => o.someProperty != null)) {
  SomeFunction(obj.someProperty);
}


You can move the if statement into a Where clause of Linq:

IEnumerable<MyClass> objects = ...
foreach(MyClass obj in objects.Where(obj => obj.someProperty != null)
{
    SomeFunction(obj.someProperty);
}

Going further, you can use List's ForEach method:

IEnumerable<MyClass> objects = ...
objects.Where(obj => obj.someProperty != null).ToList()
    .ForEach(obj => SomeFunction(obj.someProperty));

That's making the code slightly harder to read, though. Usually I stick with the typical foreach statement versus List's ForEach, but it's entirely up to you.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜