代码之家  ›  专栏  ›  技术社区  ›  stackoverflowresearch456 s

需要有关C中IEnumerable工作的帮助#

c#
  •  0
  • stackoverflowresearch456 s  · 技术社区  · 5 月前

    我想知道基本的 IEnumerable LINQ中使用的功能。

    查看我的代码:

    string[] fruits = new string[] {"apple", "plum", "cherry"};
    
    IEnumerable<string> results = from a in fruits  
                                  select a; 
    

    我的问题是:

    在第一行中,我声明了一个字符串数组,字符串数组是一个 IEnumerable 类型正确吗?

    在第二行中,我们正在初始化一个类型为的变量 IEnumerable 并应用LINQ查询来获取结果。

    即使字符串数组( fruits )是一个 IEnumerable 类型,需要将其铸造成什么 IEnumerable 再次键入?

    有人能帮我理解这个简单的问题吗。

    1 回复  |  直到 5 月前
        1
  •  4
  •   Guru Stron    5 月前

    在第一行中,我声明了一个字符串数组,字符串数组是一个IEnumerable类型,对吗?

    是的,这不仅 IEnumerable 但是 IEnumerable<string> 也。

    在第二行中,我们正在初始化一个IEnumerable类型的变量,并应用LINQ查询来获取结果

    实际上,这里没有提取结果,因为枚举是懒惰的,而且你没有应用一个会触发它的操作(比如 ToArray() , ToList() , Count() , foreach 等等)

    以下内容:

    IEnumerable<string> results = from a in fruits  
                          select a; 
    

    实际上,它是由编译器在以下内容中转换的:

    IEnumerable<string> results = fruits.Select(a => a); 
    

    这是呼叫 Enumerable.Select 扩展方法。请注意 results 是一个 IEnumerable<string> 但不是阵列,即。 Console.WriteLine(results is string[]); 将导致 False 虽然 Console.WriteLine(fruits is string[]); 很明显 True .

    另请注意 select 可以包含一些数据操作,如 select a + " is a fruit!" ,这不会改变返回值的数据类型(在提供的情况下,但您可以使用一个会改变的类型),但会导致枚举返回不同的数据。

    反编译为C# @sharplab .

    再次将其转换为IEnumerable类型有什么必要?

    没有强制转换,您正在为新变量显式定义变量类型 result .你可以用 var var result = ... (尽管编译器会确定类型是相同的- IEnumerable<string> )

        2
  •  0
  •   Ivan Petrov    5 月前

    我认为你真正的问题可能是:

    为什么LINQ的方法返回 IEnumerable<string> 而不是举例 string[] 即使 虽然 string[] 执行器 IEnumerable<string> ?

    微软可能已经为 Where 操作员:

    public static class LinqExtensions {
    
        public static C Where<C, T>(this C collection, Func<T, bool> predicate)
        where C : IEnumerable<T>, new() {
            var filtered = new C();
    
            foreach (var element in collection) {
                if (predicate(element)) {
                    // how would we add just the filtered elements though?
                    // we can only foreach because we are working on IEnumerable
                    //filtered.Add
                }
            }
            return filtered;
        }
    }
    

    然后你可以写:

    string[] filtered = stringArray.Where(x => x.Contains("foo"));
    

    如您所见,我们必须初始化一个 new C -收集以保存筛选的项目。一个问题是,我们不能 Add 它的元素,所以我们必须让它接受不 IEnumerable<T> 但是 ICollection<T> .

    但真正的问题是,我们必须在每一步都急切地构建具体的类型。

    想象一下,我们有

    string[] filteredArray = stringArray
    .Where(x => x.Contains("hello")
    .Where(x => x.Length>5);
    

    在此过程中,我们将构建两个数组。但如果我们刚回来 IEnumerable<string> 而不是 string[] 我们可以

    1. 将过滤操作延迟到稍后的时间点
    2. 可能在一个枚举步骤中应用这两个过滤器
    3. 可以选择具体实现什么类型——也许我们需要一个 List<string> 而不是 string[]