LINQ equivalent of foreach for IEnumerable

2018-12-31 03:15发布

I'd like to do the equivalent of the following in LINQ, but I can't figure out how:

IEnumerable<Item> items = GetItems();
items.ForEach(i => i.DoStuff());

What is the real syntax?

21条回答
谁念西风独自凉
2楼-- · 2018-12-31 03:31

There is an experimental release by Microsoft of Interactive Extensions to LINQ (also on NuGet, see RxTeams's profile for more links). The Channel 9 video explains it well.

Its docs are only provided in XML format. I have run this documentation in Sandcastle to allow it to be in a more readable format. Unzip the docs archive and look for index.html.

Among many other goodies, it provides the expected ForEach implementation. It allows you to write code like this:

int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8 };

numbers.ForEach(x => Console.WriteLine(x*x));
查看更多
一个人的天荒地老
3楼-- · 2018-12-31 03:32

Now we have the option of...

        ParallelOptions parallelOptions = new ParallelOptions();
        parallelOptions.MaxDegreeOfParallelism = 4;
#if DEBUG
        parallelOptions.MaxDegreeOfParallelism = 1;
#endif
        Parallel.ForEach(bookIdList, parallelOptions, bookID => UpdateStockCount(bookID));

Of course, this opens up a whole new can of threadworms.

ps (Sorry about the fonts, it's what the system decided)

查看更多
皆成旧梦
4楼-- · 2018-12-31 03:33

This "functional approach" abstraction leaks big time. Nothing on the language level prevents side effects. As long as you can make it call your lambda/delegate for every element in the container - you will get the "ForEach" behavior.

Here for example one way of merging srcDictionary into destDictionary (if key already exists - overwrites)

this is a hack, and should not be used in any production code.

var b = srcDictionary.Select(
                             x=>
                                {
                                  destDictionary[x.Key] = x.Value;
                                  return true;
                                }
                             ).Count();
查看更多
倾城一夜雪
5楼-- · 2018-12-31 03:34

Yet another ForEach Example

public static IList<AddressEntry> MapToDomain(IList<AddressModel> addresses)
{
    var workingAddresses = new List<AddressEntry>();

    addresses.Select(a => a).ToList().ForEach(a => workingAddresses.Add(AddressModelMapper.MapToDomain(a)));

    return workingAddresses;
}
查看更多
宁负流年不负卿
6楼-- · 2018-12-31 03:35

Inspired by Jon Skeet, I have extended his solution with the following:

Extension Method:

public static void Execute<TSource, TKey>(this IEnumerable<TSource> source, Action<TKey> applyBehavior, Func<TSource, TKey> keySelector)
{
    foreach (var item in source)
    {
        var target = keySelector(item);
        applyBehavior(target);
    }
}

Client:

var jobs = new List<Job>() 
    { 
        new Job { Id = "XAML Developer" }, 
        new Job { Id = "Assassin" }, 
        new Job { Id = "Narco Trafficker" }
    };

jobs.Execute(ApplyFilter, j => j.Id);

. . .

    public void ApplyFilter(string filterId)
    {
        Debug.WriteLine(filterId);
    }
查看更多
孤独寂梦人
7楼-- · 2018-12-31 03:36

Keep your Side Effects out of my IEnumerable

I'd like to do the equivalent of the following in LINQ, but I can't figure out how:

As others have pointed out here and abroad LINQ and IEnumerable methods are expected to be side-effect free.

Do you really want to "do something" to each item in the IEnumerable? Then foreach is the best choice. People aren't surprised when side-effects happen here.

foreach (var i in items) i.DoStuff();

I bet you don't want a side-effect

However in my experience side-effects are usually not required. More often than not there is a simple LINQ query waiting to be discovered accompanied by a StackOverflow.com answer by either Jon Skeet, Eric Lippert, or Marc Gravell explaining how to do what you want!

Some examples

If you are actually just aggregating (accumulating) some value then you should consider the Aggregate extension method.

items.Aggregate(initial, (acc, x) => ComputeAccumulatedValue(acc, x));

Perhaps you want to create a new IEnumerable from the existing values.

items.Select(x => Transform(x));

Or maybe you want to create a look-up table:

items.ToLookup(x, x => GetTheKey(x))

The list (pun not entirely intended) of possibilities goes on and on.

查看更多
登录 后发表回答