Linq学习__03__数据源是IEnumerable<T> 变量,Concat,匿名类,数组下标,返回字符串,group by,orderby

本文介绍了一种使用Linq进行数据查询的方法,包括如何利用Concat连接不同数据源、使用匿名类及普通类获取数据、使用数组下标筛选特定条件记录等,并通过具体示例展示了这些查询技巧的实际应用。

想运行本程序,请先做好准备工作,请参考:Linq学习__00__准备工作

(1)在HomeController创建新的方法,起名为Index1,其如代码1.1


代码1.1

#region 数据源是IEnumerable<T> 变量
        /// <summary>
        /// 数据源是IEnumerable<T> 变量
        /// 访问地址 Home/Index1
        /// Concat()方法,返回匿名类,返回正常普通类,group by
        /// </summary>
        /// <returns></returns>
        public ActionResult Index1()
        {
            // 创建学生类
            List<Student> students = new List<Student>()
            {
                new Student {First="二代",
                            Last="富",
                            ID=111,
                            Street="123 Main Street",
                            City="大连",
                            Scores= new List<int> {97, 92, 81, 60}},
                new Student {First="二麻子",
                            Last="王",
                            ID=112,
                            Street="124 Main Street",
                            City="深圳",
                            Scores= new List<int> {75, 84, 91, 39}},
                new Student {First="吊丝",
                            Last="项",
                            ID=113,
                            Street="125 Main Street",
                            City="上海",
                            Scores= new List<int> {88, 94, 65, 91}},
            };
            // 创建教师类
            List<Teacher> teachers = new List<Teacher>()
            {
                new Teacher {First="柜", Last="钱", ID=945, City = "大连"},
                new Teacher {First="斌", Last="孙", ID=956, City = "深圳"},
                new Teacher {First="廉洁", Last="李", ID=972, City = "北京"}
            };
            // 用Concat连接两个子查询,查找城市在“大连”的学生和教师
            var peopleInSeattle = (from student in students
                                   where student.City == "大连"
                                   select student.First)
                                  .Concat(from teacher in teachers
                                          where teacher.City == "大连"
                                          select teacher.First);
            ViewBag.Concat = peopleInSeattle;

            //用匿名类获取多个属性的元素,此时接收的变量是任意的
            var anonymous = from student in students
                            select new
                            {
                                First_rand = student.First,//变量是任意的
                                Last_ha_ha = student.Last//变量是任意的
                            };
            ViewBag.anonymous = anonymous;

            //用普通正常类获取多个属性的元素,此时接收的变量必须是声明的Student类的属性
            var hasNameClass = (from student in students
                                select new Student
                                 {
                                     First = student.First,//First必须是Student类的属性
                                     Last = student.Last//Last必须是Student类的属性
                                 }).ToArray();
            ViewBag.hasNameClass = hasNameClass;

            //使用数组下标,检索出第一科成绩大于80分的学生
            var studentQuery =from student in students
                              where student.Scores[0] > 80
                              select student;
            ViewBag.studentQuery = studentQuery;

            //使用对应参数返回字符串
            var studentQuery1 = from student in students
                               select string.Format("我是{0}{1}", student.Last, student.First);
            ViewBag.studentQuery1 = studentQuery1;

            //使用group by
            var studentQuery2 =from student in students
                               group student by student.Last[0];//注意,linq可以用group语句结尾,再有就是用select结尾,没有第三个了。
            ViewBag.studentQuery2 = studentQuery2;

            //分组后按字母顺序orderby
            var studentQuery3 = from student in students
                                group student by student.Last[0] into studentGroup
                                orderby studentGroup.Key
                                select studentGroup;
                                
            ViewBag.studentQuery3 = studentQuery3;

            return View();//返回View视图
        }
        #endregion 数据源是XMLIEnumerable<T> 变量


2)添加视图Index1.cshtml,代码如代码1.2


代码1.2

@{
    ViewBag.Title = "Index1";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@{
    <div style="background-color: Yellow;">
        用Concat连接两个子查询,查找城市在“大连”的学生和教师</div>
    foreach (var i in ViewBag.Concat)
    {
    <div>@i
    </div>
    }
    <br />
    <div style="background-color: Yellow;">
        用匿名类获取多个属性的元素,此时接收的变量是任意的</div>
    foreach (var j in ViewBag.anonymous)
    {
    <div>@j
    </div>
        //感兴趣的同学可以放开下面注释掉的语句执行以下,看会否成功
        @*<div>First_rand =@j.First_rand + , Last_ha_ha =@j.Last_ha_ha</div>*@
        //通过试验可知匿名类的属性是不能被调用的
    }
    <br />    
    <div style="background-color: Yellow;">
        用普通正常类获取多个属性的元素,此时接收的变量必须是声明的Student类的属性</div>
    foreach (var k in ViewBag.hasNameClass)
    {
    <div>
        First=@k.First ,Last=@k.Last</div>
    }
    <br />
    <div style="background-color: Yellow;">
        使用数组下标,检索出第一科成绩大于80分的学生</div>
    foreach (var m in ViewBag.studentQuery)
    {
    <div>
        First=@m.First ,Last=@m.Last</div>
    }
    <br />
    <div style="background-color: Yellow;">
        使用对应参数返回字符串</div>
    foreach (var n in ViewBag.studentQuery1)
    {
    <div>
        @n</div>
    }
    <br />
    <div style="background-color: Yellow;">
        使用group by,取数据要两层循环</div>
    foreach (var p in ViewBag.studentQuery2)
    {
        foreach (var g in p)
        {
    <div>我是 @g.Last @g.First</div>
        }
    }
    <br />
}


 

 

 

 


<think>好的,用户想了解C#中IEnumerable<T>和List<T>的区别以及使用场景。首先,我需要回忆这两个类型的基本概念。 IEnumerable<T>是一个接口,定义了GetEnumerator方法,允许遍历集合。它属于System.Collections.Generic命名空间,支持迭代,但本身不提供添加或删除元素的方法。而List<T>是一个具体的类,实现了IList<T>接口,提供了丰富的操作方法,比如Add、Remove等。 接下来要考虑它们的性能差异。因为IEnumerable<T>是延迟执行的,特别是在使用LINQ查询时,只有在实际遍历时才会执行查询,这有助于优化性能。而List<T>在内存中维护一个数组,访问元素速度快,但频繁的插入删除可能影响性能。 内存管理方面,IEnumerable<T>可能更节省内存,特别是在处理大型数据集时,可以逐个元素处理,不需要一次性加载所有数据。List<T>则需要连续的内存空间,存储所有元素。 使用场景的话,IEnumerable<T>适合只读遍历和延迟执行的情况,比如LINQ查询结果。而List<T>适合需要频繁修改集合或随机访问元素的场景。 还要注意转换问题,比如调用ToList()会立即执行查询并生成列表,增加内存消耗。而ToArray()类似,但返回数组。另外,协变性方面,IEnumerable<T>支持协变,可以将子类型集合赋值给父类型变量,而List<T>不支持。 需要确保引用相关的资料,比如引用[1]提到IEnumerable<T>没有Sum方法,实际是LINQ扩展方法提供的。引用[2]展示了使用LINQ处理数组的例子,说明IEnumerable<T>的应用。引用[3]提到值类型和协变性的问题,但可能和当前问题关联不大,不过协变性确实是IEnumerable<T>的一个优势。 用户可能还想知道何时选择其中之一,或者如何在实际项目中权衡。需要总结主要区别,并给出建议的使用场景,帮助用户做出决策。</think>### IEnumerable<T> vs List<T> 的区别与使用场景 #### 1. **基础定义与核心差异** - **IEnumerable<T>** 是一个接口(interface),定义了一个基础迭代器: ```csharp public interface IEnumerable<out T> : IEnumerable { IEnumerator<T> GetEnumerator(); } ``` 它仅支持**只读遍历**,无法直接修改集合元素[^1]。 - **List<T>** 是一个具体类(class),实现了 `IList<T>` 接口,提供完整的集合操作: ```csharp public class List<T> : IList<T>, ICollection<T>, IEnumerable<T> { public void Add(T item); public void Remove(T item); public T this[int index] { get; set; } // 其他方法... } ``` 支持增删改查、索引访问等操作。 #### 2. **性能与行为差异** | 特性 | IEnumerable<T> | List<T> | |---------------------|---------------------------------------------|-------------------------------------------| | **延迟执行** | ✔️ (LINQ查询时) | ❌ (数据立即加载) | | **内存占用** | 低(流式处理) | 高(需预分配连续内存) | | **修改能力** | ❌ | ✔️ | | **索引访问** | ❌ | ✔️ | | **协变性支持** | ✔️ (`IEnumerable<string>` 可转为 `IEnumerable<object>`)[^3] | ❌ (`List<string>` 无法转为 `List<object>`) | #### 3. **典型使用场景** - **IEnumerable<T>** 适用场景: - **只读遍历**:如遍历数据库查询结果、文件流等。 - **延迟执行**:LINQ查询(如 `Where`、`Select`)默认返回 `IEnumerable<T>`,避免立即加载全部数据。 ```csharp IEnumerable<string> filtered = names.Where(s => s != null); // 延迟过滤[^2] ``` - **内存敏感场景**:处理大型数据集时,逐项处理减少内存压力。 - **List<T>** 适用场景: - **频繁修改集合**:需要动态添加/删除元素。 - **随机访问元素**:通过索引快速获取元素(时间复杂度 $O(1)$)。 - **缓存结果**:将 `IEnumerable<T>` 转换为 `List<T>` 固化数据: ```csharp List<string> cachedList = filtered.ToList(); // 触发立即执行 ``` #### 4. **转换与优化** - **从 IEnumerable<T> 到 List<T>**: ```csharp List<T> list = enumerable.ToList(); // 触发数据加载 ``` 适合需要复用查询结果或避免重复计算的场景,但会增加内存占用。 - **从 List<T> 到 IEnumerable<T>**: ```csharp IEnumerable<T> enumerable = list; // 隐式转换(协变性) ``` 适合需要通用接口的API设计。 #### 5. **扩展方法支持** - **LINQ扩展方法**(如 `Sum()`、`Average()`)通过 `System.Linq` 命名空间为 `IEnumerable<T>` 添加功能: ```csharp int total = myAccounts.Sum(a => a.Balance); // 依赖LINQ扩展[^1] ``` 这些方法不直接属于 `IEnumerable<T>` 接口,而是通过扩展方法实现。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值