0

Can I get the latest file within foreach loop without calculating last variable using LastOrDefault ?

I don't want to repeat archive.Entries.OrderBy(x => x.LastWriteTime) 2 times

var last = archive.Entries.OrderBy(x => x.LastWriteTime).LastOrDefault();

        foreach (var entry in archive.Entries.OrderBy(x => x.LastWriteTime))
        {
            Console.WriteLine(entry.Equals(last) ? $"latest file: {entry.Name}" : entry.Name);
        }
user584018
  • 10,186
  • 15
  • 74
  • 160
  • What are you trying to accomplish? – Slava Knyazev Feb 02 '23 at 04:24
  • I don't want to repeat `archive.Entries.OrderBy(x => x.LastWriteTime)` 2 times – user584018 Feb 02 '23 at 04:26
  • 1
    Possibly that you can store the `IQueryable`/ `IOrderQueryable` into a variable. `var orderQuery = archive.Entries.OrderBy(x => x.LastWriteTime);` Then you can use the variable to avoid duplication. `var last = orderQuery.Last();` – Yong Shun Feb 02 '23 at 04:28
  • Note that it is deferred execution when declare into the variable (`IQueryable`). It won't materialize until call methods such: as `ToList()`, `Last()`, `First()`... – Yong Shun Feb 02 '23 at 04:34
  • @YongShun. thanks, but I am getting warning `possible multiple enumeration` for variable `orderQuery`, how to avoid it? – user584018 Feb 02 '23 at 04:41
  • Perhaps use `.ToList()` in `foreach (var entry in orderQuery.ToList())`. Maybe you can have a read on this question: [Resharper's example code for explaining "Possible multiple enumeration of IEnumerable"](https://stackoverflow.com/questions/20129079/resharpers-example-code-for-explaining-possible-multiple-enumeration-of-ienume) – Yong Shun Feb 02 '23 at 04:49

1 Answers1

2

You can break the chain of LINQ queries at any point and resume in another context.

// Note: ToArray() is necessary to prevent double-enumeration in the case of a Queryable set. 
// It's not necessary for constructs which are already enumerated
var ordered = archive.Entries.OrderBy(x => x.LastWriteTime).ToArray(); 
var last = ordered.LastOrDefault();

foreach (var entry in ordered)
        {
            Console.WriteLine(entry.Equals(last) ? $"latest file: {entry.Name}" : entry.Name);
        }
Slava Knyazev
  • 5,377
  • 1
  • 22
  • 43
  • That doesn't really help. It makes the code a bit more succinct but the LINQ query is still executed twice. – jmcilhinney Feb 02 '23 at 04:39
  • thanks. I am getting `possible multiple enumeration` for variable `ordered`, how to avoid it? – user584018 Feb 02 '23 at 04:39
  • 1
    I updated the answer. I assumed Entries wasn't an Queryable. ToArray/ToList/toCollection() will enumerate the full set once. The answer technically "avoids duplicating the code" which the question called for. Duplication of the enumeration wasn't mentioned at the time. – Slava Knyazev Feb 02 '23 at 04:52