tags:

views:

1736

answers:

4

Hi

I have recently started off with LINQ and its amazing. I was wondering if LINQ would allow me to apply a function - any function - to all the elements of a collection, without using foreach. Something like python lambda functions.

For example if I have a int list, Can I add a constant to every element using LINQ

If i have a DB table, can i set a field for all records using LINQ.

I am using C#

+3  A: 

The idiomatic way to do this with LINQ is to process the collection and return a new collection mapped in the fashion you want. For example, to add a constant to every element, you'd want something like

var newNumbers = oldNumbers.Select(i => i + 8);

Doing this in a functional way instead of mutating the state of your existing collection frequently helps you separate distinct operations in a way that's both easier to read and easier for the compiler to reason about.

If you're in a situation where you actually want to apply an action to every element of a collection (an action with side effects that are unrelated to the actual contents of the collection) that's not really what LINQ is best suited for, although you could fake it with Select (or write your own IEnumerable extension method, as many people have.) It's probably best to stick with a foreach loop in that case.

mquander
Not to mention mutating a collection while iterating over it is dangerous, to impossible, depending on the language.
Soviut
In C#, mutating the elements of the collection is fair game, but adding to or removing from the collection may either fail or yield unwanted results.
mquander
using the Select method only really helps with certain types, like int. What if you wanted to set the property of the objects in your list to a certain value? wouldn't it be simpler and more scalable to use .ForEach()?
andy
If you already knew the new value, then typically (in the spirit of LINQ) you would tend to make a new list with the appropriate values in it, instead of changing the old one. Of course, if you do have a list and you really want to change that particular list -- maybe it's databound to something -- then .ForEach() is fine, too.
mquander
+3  A: 

haha, man, I just asked this question a few hours ago (kind of)...try this:

example:

someIntList.ForEach(i=>i+5);

ForEach() is one of the built in .NET methods

This will modify the list, as opposed to returning a new one.

andy
Note that this only works on actual List<T> collections, unless you've defined your own ForEach method to do it.
mquander
yeah, I guess I'm assuming you'd only want to edit an object you already have in memory, but yeah, you're right. never assume!
andy
I believe mquander was referring to the fact that ForEach is not defined on IEnumerable<T>, just List<T>
Odrade
Yes, it won't work in most cases, because usually you will get an IEnumerable from your link query
huttelihut
+7  A: 

A common way to approach this is to add your own ForEach generic method on IEnumerable<T>. Here's the one we've got in MoreLINQ:

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    source.ThrowIfNull("source");
    action.ThrowIfNull("action");
    foreach (T element in source)
    {
        action(element);
    }
}

(Where ThrowIfNull is an extension method on any reference type, which does the obvious thing.)

It'll be interesting to see if this is part of .NET 4.0. It goes against the functional style of LINQ, but there's no doubt that a lot of people find it useful.

Once you've got that, you can write things like:

people.Where(person => person.Age < 21)
      .ForEach(person => person.EjectFromBar());
Jon Skeet
I never really understood the urge people have to do that. A foreach loop is more readable to my eyes; having a separation between the "functional" part that gets the data and the "action" part that operates on it helps clarify the structure of algorithms.
mquander
Yes, I generally prefer a foreach loop myself. On the other hand, if you've already been presented with a delegate to apply to each element, I'm not sure it's much more readable to call that delegate in an explicit foreach loop. I wouldn't use this often, but just occasionally it seems like a nice solution.
Jon Skeet
You might use this to solve the problem in question: datetimes = datetimes.Select ( itm => itm.AddDays ( 1 ).AddHours ( 6 ) ).ToArray ();
Sascha
@Sascha: I fail to see how your comment relates to this question.
Jon Skeet
I was on the wrong page and commented in err. Thought I had deleted the comment...
Sascha
A: 

You can try something like

var foo = (from fooItems in context.footable select fooItems.fooID + 1);

Returns a list of id's +1, you can do the same with using a function to whatever you have in the select clause.

Update: As suggested from Jon Skeet this is a better version of the snippet of code I just posted:

var foo = context.footable.Select(foo => foo.fooID + 1);
Drahcir
I'd suggest that in cases where you just need to do a simple projection, query expressions are over the top. I'd use "var foo = context.footable.Select(foo => foo.fooID + 1);"
Jon Skeet
I see, still relatively new to linq, still learning as I go. Thanks for the advise
Drahcir