Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IEnumerable vs List-使用什么?它们是如何工作的?_C#_Linq_List_Ienumerable - Fatal编程技术网

C# IEnumerable vs List-使用什么?它们是如何工作的?

C# IEnumerable vs List-使用什么?它们是如何工作的?,c#,linq,list,ienumerable,C#,Linq,List,Ienumerable,我对统计员的工作方式有些怀疑,LINQ。考虑这两个简单的选择: List<Animal> sel = (from animal in Animals join race in Species on animal.SpeciesKey equals race.SpeciesKey select animal).Distinct().ToList(); 我注意到,如

我对统计员的工作方式有些怀疑,LINQ。考虑这两个简单的选择:

List<Animal> sel = (from animal in Animals 
                    join race in Species
                    on animal.SpeciesKey equals race.SpeciesKey
                    select animal).Distinct().ToList();
  • 我注意到,如果我使用
    IEnumerable
    ,当我调试和检查“sel”(在这种情况下是IEnumerable)时,它有一些有趣的成员:“内部”、“外部”、“内部KeySelector”和“外部KeySelector”,最后两个似乎是委托。“内部”成员中没有“动物”实例,而是“物种”实例,这对我来说非常奇怪。“外部”成员不包含“动物”实例。我想这两位代表会决定哪一位进入,哪一位退出

  • 我注意到,如果我使用“Distinct”,则“inner”包含6项(这是不正确的,因为只有2项是Distinct的),但“outer”包含正确的值。同样,可能是委托方法决定了这一点,但这比我对IEnumerable的了解要多一些

  • 最重要的是,这两个选项中哪一个性能最好

  • 通过
    .ToList()
    进行邪恶列表转换

    或者直接使用枚举器


    如果可以的话,也请解释一下或抛出一些链接来解释IEnumerable的用法。

    要了解的最重要的一点是,使用Linq时,查询不会立即得到计算。它只作为在
    foreach
    中迭代生成的
    IEnumerable
    的一部分运行-这就是所有奇怪的委托所做的

    因此,第一个示例通过调用
    ToList
    并将查询结果放入列表中,立即对查询进行评估。
    第二个示例返回一个
    IEnumerable
    ,其中包含以后运行查询所需的所有信息


    就性能而言,答案是视情况而定。如果您需要立即评估结果(例如,您正在修改稍后查询的结构,或者如果您不想在
    IEnumerable
    上进行迭代需要很长时间),请使用列表。否则请使用
    IEnumerable
    。在第二个示例中,默认情况下应该使用按需求值,因为这通常使用较少的内存,除非有特定的原因将结果存储在列表中。

    要了解的最重要的一点是,使用Linq,查询不会立即得到求值。它只作为在
    foreach
    中迭代生成的
    IEnumerable
    的一部分运行-这就是所有奇怪的委托所做的

    因此,第一个示例通过调用
    ToList
    并将查询结果放入列表中,立即对查询进行评估。
    第二个示例返回一个
    IEnumerable
    ,其中包含以后运行查询所需的所有信息


    就性能而言,答案是视情况而定。如果您需要立即评估结果(例如,您正在修改稍后查询的结构,或者如果您不想在
    IEnumerable
    上进行迭代需要很长时间),请使用列表。否则请使用
    IEnumerable
    。在第二个示例中,默认情况下应该使用按需求值,因为这通常会占用较少的内存,除非有特定原因将结果存储在列表中。

    如果您只想枚举它们,请使用
    IEnumerable


    不过,请注意,更改正在枚举的原始集合是一项危险的操作—在本例中,您将首先希望
    ToList
    。这将为内存中的每个元素创建一个新的列表元素,枚举
    IEnumerable
    ,因此,如果只枚举一次,则性能较低,但更安全,有时
    list
    方法很方便(例如在随机访问中)。

    如果您只想枚举它们,请使用
    IEnumerable


    不过,请注意,更改正在枚举的原始集合是一项危险的操作—在本例中,您将首先希望
    ToList
    。这将为内存中的每个元素创建一个新的列表元素,枚举
    IEnumerable
    ,因此,如果只枚举一次,则性能较低,但更安全,而且有时
    list
    方法很方便(例如在随机访问中)。

    IEnumerable的优点是延迟执行(通常在数据库中)。在实际循环数据之前,不会执行查询。这是一个等待需要它的查询(也称为延迟加载)

    如果您调用ToList,查询将被执行,或者如我所说的“物化”


    两者都有利弊。如果调用ToList,可以消除查询何时执行的一些秘密。如果你坚持使用IEnumerable,你会得到一个好处,那就是程序在实际需要它之前不会做任何工作。

    IEnumerable的好处是延迟执行(通常使用数据库)。在实际循环数据之前,不会执行查询。这是一个等待需要它的查询(也称为延迟加载)

    如果您调用ToList,查询将被执行,或者如我所说的“物化”


    两者都有利弊。如果调用ToList,可以消除查询何时执行的一些秘密。如果你坚持使用IEnumerable,你会得到一个好处,那就是程序在实际需要之前不会做任何工作。

    一个实现了
    IEnumerable
    的类允许你使用
    foreach
    语法

    基本上,它有一个方法来获取集合中的下一项。它不需要将整个集合存储在内存中,也不知道其中有多少项,
    foreach
    只是不断获取下一项,直到它用完为止

    在某些情况下,这可能非常有用,例如在大型数据库表中,您不希望在开始处理行之前将整个内容复制到内存中

    现在
    List
    实现了
    IEnumerable
    ,但表示
    IEnumerable<Animal> sel = (from animal in Animals 
                               join race in Species
                               on animal.SpeciesKey equals race.SpeciesKey
                               select animal).Distinct();
    
    foreach (Animal animal in sel) { /*do stuff*/ }
    
    var things = 
        from item in BigDatabaseCall()
        where ....
        select item;
    
    // this will iterate through the entire linq statement:
    int count = things.Count();
    
    // this will stop after iterating the first one, but will execute the linq again
    bool hasAnyRecs = things.Any();
    
    // this will execute the linq statement *again*
    foreach( var thing in things ) ...
    
    // this will copy the results to a list in memory
    var list = things.ToList()
    
    // this won't iterate through again, the list knows how many items are in it
    int count2 = list.Count();
    
    // this won't execute the linq statement - we have it copied to the list
    foreach( var thing in list ) ...
    
    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;
    }
    
    var Leopards = Feline(AllSpotted());
    var Hyenas = Canine(AllSpotted());
    
    List<Animals> Leopards = Feline(AllSpotted()).ToList();
    List<Animals> Hyenas = Canine(AllSpotted()).ToList();
    
    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() );
    
    // I was expecting    
    print( startingWith_M.ToList() ); // mercedes, mazda
    print( startingWith_F.ToList() ); // fiat, ferrari
    
    // what printed actualy   
    print( startingWith_M.ToList() ); // mazda
    print( startingWith_F.ToList() ); // ford, fiat, ferrari
    
    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() );