C # laziness question

What is the overall approach to the design of applications that rely heavily on lazy evaluation in the C#( LINQ, IEnumerable, IQueryable...)?

Currently, I usually try to make every request as lazy as possible using queries yield returnand LINQ, but at runtime it can usually lead to "too lazy" behavior when each request gets its initial values ​​from it, which leads to a serious deterioration in image quality.

What I usually do is put projection operators ToList()somewhere to cache data, but I suspect this approach might be wrong.

What are the appropriate / common ways to develop such applications from the start?

+5
source share
6 answers

I find it useful to classify each IEnumerable into one of three categories.

  • fast - e.g. lists and arrays
  • slow - for example. database queries or heavy computing
  • not deterministic - i.e. list.Select (x => new {...})

For category 1, I usually store a specific type, arrays or IList, etc. For category 3, it is best to maintain a local method to avoid difficulty finding errors. Then we have category 2, and as always, when optimizing performance, first measure the bottlenecks.

+4
source

A few random thoughts - since the question itself is poorly defined:

  • Lazy , , . , , .
  • . ORM
  • Lazy , MEF
+2

, , : . Lazy-load , .

, IEnumerables , .

, . , IEnumerables - , . , . , ..

+2

ToList DAL DTO

public IList<UserDTO> GetUsers()
{
  using (var db = new DbContext())
  {
    return (from u in db.tblUsers
           select new UserDTO()
           {
               Name = u.Name
           }).ToList();
  }
}

ToList() DbContext.

+2

, (ToList, ToArray ..) . .

. ? . ? Cache, , .

+1

Deferred execution and caching of all elements using .ToList()are not the only parameters. The third option is to cache the elements , as you execute, using the lazy list.

Execution is still delayed, but all items are returned only once. An example of how this work:

public class LazyListTest
{
    private int _count = 0;

    public void Test()
    {
        var numbers = Enumerable.Range(1, 40);
        var numbersQuery = numbers.Select(GetElement).ToLazyList(); // Cache lazy
        var total = numbersQuery.Take(3)
            .Concat(numbersQuery.Take(10))
            .Concat(numbersQuery.Take(3))
            .Sum();
        Console.WriteLine(_count);
    }

    private int GetElement(int value)
    {
        _count++;
        // Some slow stuff here...
        return value * 100;
    }
}

If you run the Test () method, there _countwill only be 10. Without caching, it will be 16 s. ToList()it will be 40!

An example implementation of LazyList can be found here .

0
source

All Articles