IEnumerable vs List - What to Use? How do they work?

后端 未结 10 2102
臣服心动
臣服心动 2020-11-22 03:57

I have some doubts over how Enumerators work, and LINQ. Consider these two simple selects:

List sel = (from animal in Animals 
                         


        
相关标签:
10条回答
  • 2020-11-22 04:27

    I will share one misused concept that I fell into one day:

    var names = new List<string> {"mercedes", "mazda", "bmw", "fiat", "ferrari"};
    
    var startingWith_M = names.Where(x => x.StartsWith("m"));
    
    var startingWith_F = names.Where(x => x.StartsWith("f"));
    
    
    // updating existing list
    names[0] = "ford";
    
    // Guess what should be printed before continuing
    print( startingWith_M.ToList() );
    print( startingWith_F.ToList() );
    

    Expected result

    // I was expecting    
    print( startingWith_M.ToList() ); // mercedes, mazda
    print( startingWith_F.ToList() ); // fiat, ferrari
    

    Actual result

    // what printed actualy   
    print( startingWith_M.ToList() ); // mazda
    print( startingWith_F.ToList() ); // ford, fiat, ferrari
    

    Explanation

    As per other answers, the evaluation of the result was deferred until calling ToList or similar invocation methods for example ToArray.

    So I can rewrite the code in this case as:

    var names = new List<string> {"mercedes", "mazda", "bmw", "fiat", "ferrari"};
    
    // updating existing list
    names[0] = "ford";
    
    // before calling ToList directly
    var startingWith_M = names.Where(x => x.StartsWith("m"));
    
    var startingWith_F = names.Where(x => x.StartsWith("f"));
    
    print( startingWith_M.ToList() );
    print( startingWith_F.ToList() );
    

    Play arround

    https://repl.it/E8Ki/0

    0 讨论(0)
  • 2020-11-22 04:33

    IEnumerable describes behavior, while List is an implementation of that behavior. When you use IEnumerable, you give the compiler a chance to defer work until later, possibly optimizing along the way. If you use ToList() you force the compiler to reify the results right away.

    Whenever I'm "stacking" LINQ expressions, I use IEnumerable, because by only specifying the behavior I give LINQ a chance to defer evaluation and possibly optimize the program. Remember how LINQ doesn't generate the SQL to query the database until you enumerate it? Consider this:

    public IEnumerable<Animals> AllSpotted()
    {
        return from a in Zoo.Animals
               where a.coat.HasSpots == true
               select a;
    }
    
    public IEnumerable<Animals> Feline(IEnumerable<Animals> sample)
    {
        return from a in sample
               where a.race.Family == "Felidae"
               select a;
    }
    
    public IEnumerable<Animals> Canine(IEnumerable<Animals> sample)
    {
        return from a in sample
               where a.race.Family == "Canidae"
               select a;
    }
    

    Now you have a method that selects an initial sample ("AllSpotted"), plus some filters. So now you can do this:

    var Leopards = Feline(AllSpotted());
    var Hyenas = Canine(AllSpotted());
    

    So is it faster to use List over IEnumerable? Only if you want to prevent a query from being executed more than once. But is it better overall? Well in the above, Leopards and Hyenas get converted into single SQL queries each, and the database only returns the rows that are relevant. But if we had returned a List from AllSpotted(), then it may run slower because the database could return far more data than is actually needed, and we waste cycles doing the filtering in the client.

    In a program, it may be better to defer converting your query to a list until the very end, so if I'm going to enumerate through Leopards and Hyenas more than once, I'd do this:

    List<Animals> Leopards = Feline(AllSpotted()).ToList();
    List<Animals> Hyenas = Canine(AllSpotted()).ToList();
    
    0 讨论(0)
  • 2020-11-22 04:33

    If all you want to do is enumerate them, use the IEnumerable.

    Beware, though, that changing the original collection being enumerated is a dangerous operation - in this case, you will want to ToList first. This will create a new list element for each element in memory, enumerating the IEnumerable and is thus less performant if you only enumerate once - but safer and sometimes the List methods are handy (for instance in random access).

    0 讨论(0)
  • 2020-11-22 04:34

    In addition to all the answers posted above, here is my two cents. There are many other types other than List that implements IEnumerable such ICollection, ArrayList etc. So if we have IEnumerable as parameter of any method, we can pass any collection types to the function. Ie we can have method to operate on abstraction not any specific implementation.

    0 讨论(0)
提交回复
热议问题