1

Can the following be done in LINQ as a one-liner, without using a for-loop?

IEnumerable<MyObj> MyList = EF.GetList(etc);
foreach (var row in MyList)
{
    row.uploadedAt = MyUtils.ConvertToLocalTime(row.uploadedAtUTC, clientTimezone);
}
//return MyList, which now has both dates in LocalTime and UTC
joedotnot
  • 4,810
  • 8
  • 59
  • 91
  • 1
    Attached duplicate has a couple of solution, but iterating using `foreach` seems to the cleanest way. Btw, there is no magic in `Linq`, it's still using looping under the hood – Pavel Anikhouski Jul 20 '20 at 07:05
  • There's also LINQ method `ForEach`, which does exactly what it seems to do :) Also there is [asynchronous version](https://learn.microsoft.com/en-us/dotnet/api/system.data.entity.queryableextensions.foreachasync?view=entity-framework-6.2.0) `ForEachAsync` – Michał Turczyn Jul 20 '20 at 07:12
  • @MichalTurczyn Is `ForEach` in LINQ? I am aware of no such method. – mjwills Jul 20 '20 at 08:09
  • 1
    @mjwills you are right. Not LINQ, List has ForEach method. `MyList.ToList().ForEach(x=>...)` – Cihan Yakar Jul 20 '20 at 08:22

2 Answers2

1

In addition to given answers, there's List<T> method (reference) that mimics foreach loop:

EF.GetList(etc).ToList()
    .ForEach(row => row.uploadedAt = MyUtils.ConvertToLocalTime(row.uploadedAtUTC, clientTimezone));

But I don't see any advantage of simplifying things, that are already simple enough.

IMO, too much simplification leads to maintanance horror and reduces readability :)

Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
0

Reassign the list, ideally without mutating anything. This would be more consistent with the functional programming mindset of LINQ.

IEnumerable<MyObj> myList1 = EF.GetList(etc);
IEnumerable<MyObj> myList2 = myList1.Select( x => 
        new MyObj 
        {
            uploadedAt = MyUtils.ConvertToLocalTime(x.uploadedAtUTC, x.clientTimezone),
            anyOtherFields = x.anyOtherFields
        }
    ).ToList();

If constructing a MyObj is complicated and/or you really need to mutate it, you can also do this:

IEnumerable<MyObj> myList = EF.GetList(etc);
myList = myList.Select( x => {
        x.uploadedAt = MyUtils.ConvertToLocalTime(x.uploadedAtUTC, x.clientTimezone);
        return x;
    }).ToList();

But if you're going to do it that way, you may as well use the for loop.

John Wu
  • 50,556
  • 8
  • 44
  • 80
  • your second answer is what i tried to do myself, but was stuck with returning the whole object (return x in your answer). Thanks. – joedotnot Jul 20 '20 at 07:34