C#之LINQ学习笔记

C#之LINQ学习笔记

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Linq
{
    class Program
    {
        delegate void NoReturnNoPara();//无返回值无参数委托类型
        delegate void NoReturnWithPara(int x, int y);//无返回值有参数委托类型
        delegate int WithReturnWithPara(int x, int y);//有返回值有参数委托类型

        static void Main(string[] args)
        {
            LambdaShow();//Lambda表达式
            AnonymousClassShow();//匿名类
            ExtendFunc();//扩展方法
            LinqShow();//Linq方法
            
            Console.ReadKey();
        }
        #region 基础知识
        /// <summary>
        /// Lambda表达式
        /// </summary>
        static void LambdaShow()
        {
            {//委托的实例化
                NoReturnNoPara method = new NoReturnNoPara(Dothing);
                method.Invoke();
            }
            {//匿名方法
                NoReturnNoPara method = new NoReturnNoPara(delegate ()
                {
                    Console.WriteLine("This is Dothing");
                });
                method.Invoke();
            }
            {//Lambda  左边是参数列表,中间=>是goes to,有边是方法体,本质是一个方法
                NoReturnNoPara method = new NoReturnNoPara(() =>
                {
                    Console.WriteLine("This is Dothing");
                });
                method.Invoke();
            }
            {//带参数
                NoReturnWithPara method = new NoReturnWithPara((int x, int y) =>
                {
                    Console.WriteLine("This is Dothing");
                });
                method.Invoke(1, 2);
            }
            {//带参数,省略参数类型
                NoReturnWithPara method = new NoReturnWithPara((x, y) =>
                {
                    Console.WriteLine("This is Dothing");
                });
                method.Invoke(1, 2);
            }
            {//方法体只有一行时可以省略大括号
                NoReturnWithPara method = new NoReturnWithPara((x, y) => Console.WriteLine("This is Dothing"));
                method.Invoke(1, 2);
            }
            {//实例委托时可以省略:new NoReturnWithPara,编译器自动推算
                NoReturnWithPara method = ((x, y) => Console.WriteLine("This is Dothing"));
                method.Invoke(1, 2);
            }//Lambda表达式是什么?
            //首先不是委托,委托是类型
            //然后也不是委托的实例,因为这里省略new 委托()
            //它的作用和方法是一样的
            //它的实质是一个类中类的internal方法,被绑定的一个静态的委托类型字段
            {
                NoReturnWithPara Method = new NoReturnWithPara((x, y) => Console.WriteLine("This is Dothing"));
                Method += new NoReturnWithPara((x, y) => Console.WriteLine("This is Dothing"));
                Method -= new NoReturnWithPara((x, y) => Console.WriteLine("This is Dothing"));
                Method.Invoke(1, 2);//会执行两次,-=无法去掉已经注册的方法,以为new创建的两个对象虽然相同,但不是同一个

            }
        }

        /// <summary>
        /// 匿名类
        /// </summary>
        static void AnonymousClassShow()
        {
            //匿名类
            object oModel = new
            {
                Id = 2,
                Name = "undefined",
                Age = 25,
                ClassId = 2
            };
            //Console.WriteLine(oModel.Id);object编译器不允许,无法直接访问,通过反射访问
            Type oType = oModel.GetType();
            PropertyInfo propertyInfo = oType.GetProperty("Id");
            Console.WriteLine(propertyInfo.GetValue(oModel));
            //propertyInfo.SetValue(oModel, 3);//匿名类是只读,无法写入
            dynamic dModel = new//dynamic可以避开编译器的检查,可以直接访问
            {
                Id = 2,
                Name = "undefined",
                Age = 25,
                ClassId = 2
            };
            //dModel.Id = 3;//实例是只读,所以不能赋值
            Console.WriteLine(dModel.Id);
            var varModel = new//编译后是有一个真实的类,可以直接访问,但类的字段都是只读
            {
                Id = 2,
                Name = "undefined",
                Age = 25,
                ClassId = 2
            };
            //varModel.Id = 3;//实例是只读,所以不能赋值
            Console.WriteLine(varModel.Id);

            int i2 = 2;
            var i1 = 1;//var是语法糖,由编译器自动推算类似
            var ss = "superman";
            //var aa;//var必须在声明的时候就确定类型
            //ss = 123;//确定类型后不能更改

            //var、object和dynamic的区别:
            //var是推算出来的类型,可能是任意一种类型。
            //object是一种确定的类型,它是所有类型的基类
            //dynamic是一个复杂类型,在编译的时候不知道它是什么类型,它只是避开编译器检查,如果失败就会报错。
        }

        /// <summary>
        /// 扩展方法
        /// </summary>
        static void ExtendFunc()
        {
            Student student = new Student()
            {
                Id = 1,
                ClassId = 1,
                Name = "xiaoming",
                Age = 22,
            };
            student.Study();
            student.StudyHard();
            //又要增加方法,又不能修改类时,采用扩展方法,使用别人的库文件时
            student.Sing();//调用扩展方法
            ExtendMethod.Sing(student);//普通的调用静态方法
            //泛型扩展方法
            student.ExtendShow();
            //重复扩展方法,编译无错,调用错误:二义性

            //没有扩展属性,partial类可以扩展属性

            //int? 可空类型
            int? iValue1 = null;
            int? iValue = 2;
            int value=iValue1.ToInt();
            int length = iValue.Length();
        }
        static void Dothing()
        {
            Console.WriteLine("This is Dothing");
        }

        #region  Linq

        #region  Data Init
        /// <summary>
        /// 构造一个Student类对象的List
        /// </summary>
        /// <returns></returns>
        public static List<Student> GetStudentList()
        {
            List<Student> list = new List<Student>()
            {
                new Student
                {
                    Id=1,
                    ClassId=1,
                    Name="xiaoming",
                    Age=24
                },
                new Student
                {
                    Id=2,
                    ClassId=2,
                    Name="xiaofang",
                    Age=34
                },
                new Student
                {
                    Id=3,
                    ClassId=3,
                    Name="xiaohua",
                    Age=33
                },
                new Student
                {
                    Id=4,
                    ClassId=4,
                    Name="xiaojia",
                    Age=27
                },
                new Student
                {
                    Id=5,
                    ClassId=5,
                    Name="xiaocheng",
                    Age=33
                },
                new Student
                {
                    Id=6,
                    ClassId=6,
                    Name="xiaofu",
                    Age=27
                },
            };
            return list;
        }
        #endregion
        public static void LinqShow()
        {
            List<Student> studentList = GetStudentList();
            {//常规情况下过滤数据
                var list = new List<Student>();
                foreach (var item in studentList)
                {
                    //Thread.Sleep(500);
                    Console.WriteLine("判断数据");
                    if (item.Age < 30)
                    {
                        list.Add(item);
                    }
                }
            }

            #region  Linq To Object(Enumerable)
            {//采用Linq方法
                //使用Student类型的扩展方法
                var result = studentList.CgcWhere(s => s.Age < 30);//陈述式语法,CgcWhere扩展方法
                //使用泛型扩展方法GenericCgcWhere
                new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.GenericCgcWhere(i => i < 5);
                //使用迭代器的扩展方法
                var result1 = studentList.YieldCgcWhere(s =>
                  {
                      Console.WriteLine("判断数据");
                      //Thread.Sleep(500);
                      return s.Age < 30;
                  });//在这里并不会执行扩展方法
                foreach(var item in result1)
                {
                    Console.WriteLine(item);
                }//只有在使用时才去执行扩展方法
            }
            {//Where:完成对数据集合的过滤,通过委托封装完成通用代码,泛型+迭代器去提供特性
                var linq = studentList.Where(s =>
                  {
                      Console.WriteLine("判断数据");
                      //Thread.Sleep(500);
                      return s.Age < 30;
                  });
            }
            {
                //Select:完成对数据集合的转换,通过委托封装完成通用代码,泛型+迭代器去提供特性
                var linq = studentList.
                    Where(s =>
                {
                    Console.WriteLine("判断数据");
                    //Thread.Sleep(500);
                    return s.Age < 30;
                })
                .Select<Student, int>(s => s.Name.Length);
            }
            {
                //Select:完成对数据集合的转换,通过委托封装完成通用代码,泛型+迭代器去提供特性
                var linq = studentList
                    .Where(s =>
                    {
                        Console.WriteLine("判断数据");
                        //Thread.Sleep(500);
                        return s.Age < 30;
                    })
                    .Select(s => new
                    {
                        Id=s.Id,
                        Name=s.Name,
                        Length=s.Name.Length
                    });
                foreach(var item in linq)
                {
                    //item.Id;
                    //item.Name;
                }
            }
            {
                //Min/Max/OrderBy/GroupBy等:完成对数据集合的转换,通过委托封装完成通用代码,泛型+迭代器(有些没有)去提供特性
                {
                    Console.WriteLine("********Ling To Object********");
                    var list = studentList.Where<Student>(s => s.Age < 30);
                    foreach (var item in list)
                        Console.WriteLine("Name={0} Age={1}", item.Name, item.Age);
                }
                {
                    Console.WriteLine("与上面的效果一致");
                    var list = from s in studentList
                               where s.Age < 30
                               select s;
                    foreach (var item in list)
                        Console.WriteLine("Name={0} Age={1}", item.Name, item.Age);
                }
                {
                    Console.WriteLine("投影,转换成一个新的对象");
                    var list = studentList.Where(s => s.Age < 30).Select(s => new
                    {
                        IdName = s.Id + s.Name,
                        ClassName = s.ClassId == 2 ? "高级班" : "其他班"
                    });
                    foreach (var item in list)
                        Console.WriteLine("IdName={0} ClassName={1}", item.IdName, item.ClassName);
                }
                {
                    Console.WriteLine("与上一个相同");
                    var list = from s in studentList
                               where s.Age < 30
                               select new
                               {
                                   IdName = s.Id + s.Name,
                                   ClassName = s.ClassId == 2 ? "高级班" : "其他班"
                               };
                    foreach (var item in list)
                        Console.WriteLine("IdName={0} ClassName={1}", item.IdName, item.ClassName);
                }
                {
                    Console.WriteLine("条件筛选");
                    var list = studentList.Where(s => s.Age < 80).Select(s => new
                    {
                        Id = s.Id,
                        ClassId = s.ClassId,
                        IdName = s.Id + s.Name,
                        ClassName = s.ClassId == 2 ? "高级班" : "其他班"
                    }).OrderBy(s => s.Id)//递增排序
                    .OrderByDescending(s => s.ClassId)//递减排序
                    .Skip(2)//跳过几条,之前需要先排序
                    .Take(3);//获取几条,之前需要先排序
                    foreach (var item in list)
                        Console.WriteLine("IdName={0} ClassName={1}", item.IdName, item.ClassName);
                }
                {
                    Console.WriteLine("GroupBy");
                    var list = from s in studentList
                               where s.Age < 80
                               group s by s.ClassId into sg
                               select new
                               {
                                   key = sg.Key,
                                   maxAge = sg.Max(t => t.Age)
                               };
                    foreach (var item in list)
                        Console.WriteLine($"key={item.key} ClassName={item.maxAge}");
                }
                List<Class> classList = new List<Class>()
                {
                    new Class()
                    {
                        Id=1,
                        ClassName="初级班"
                    },
                    new Class()
                    {
                        Id=2,
                        ClassName="高级班"
                    },
                    new Class()
                    {
                         Id=3,
                        ClassName="网络班"
                    },
                };

                {
                    Console.WriteLine("关联表:关键字形式");
                    var list = from s in studentList
                               join c in classList on s.ClassId equals c.Id
                               select new
                               {
                                   Name = s.Name,
                                   ClassName = c.ClassName
                               };
                    foreach (var item in list)
                        Console.WriteLine($"Name={item.Name},ClassName={item.ClassName}");
                }
                {
                    Console.WriteLine("关联表:扩展方法形式");
                    var list = studentList.Join(classList, s => s.ClassId, c => c.Id, (s, c) => new
                    {
                        Name = s.Name,
                        ClassName = c.ClassName
                    });
                    foreach (var item in list)
                        Console.WriteLine($"Name={item.Name} ClassName={item.ClassName}");
                }
                {
                    Console.WriteLine("左连接:关键字形式");
                    var list = from s in studentList
                               join c in classList on s.ClassId equals c.Id
                               into scList
                               from sc in scList.DefaultIfEmpty()
                               select new
                               {
                                   Name = s.Name,
                                   ClassName = sc == null ? "无班级" : sc.ClassName//c变sc,为空则用
                               };
                    foreach (var item in list)
                        Console.WriteLine($"Name={item.Name}  ClassName={item.ClassName}");
                }
                //右连接则将s和c的位置交换一下即可,没有右连接的写法形式
                {
                    Console.WriteLine("左连接:扩展方法形式");
                    var list = studentList.Join(classList, s => s.ClassId, c => c.Id, (s, c) => new
                    {
                        Name = s.Name,
                        ClassName = c.ClassName
                    });
                    foreach (var item in list)
                        Console.WriteLine($"Name={item.Name}  ClassName={item.ClassName}");
                }
                //以上的关键字编译后都变成了扩展方法形式,相当于关键字其实是语法糖,由编译器提供的

                int? value = null;//可空类型:指向Nullable<int>,与int相比是另一种类型
                int value1 = default(int);//默认值为0
                int? value2 = default(int?);//默认值为null
                int? value3 = 3;
                int? value4 = new int?(3);
                int? value5 = new Nullable<int>(3);
                int value6 = (int)value4;//int?转换为int
                int sum = value1 + (int)value3;
                int? sum1 = value1 + value3;
                value1 = 5;
                value3 = null;
                int? sum2 = value1 + value3;//任何int值与值为null的int?运算结果为null  
            }
        }
            #endregion
            //Lambda声明属性
        public int id => 3;
        public void ShowLambda() => Console.WriteLine("LambdaFunc");

        //Linq To Sql(Queryable):SQL+ADO.NET
        //Where:完成对数据库的过滤,封装通用代码。

        //Linq To XML

        //Linq To Excel/Nosql

        //Linq To Everything
    }

        #endregion

    /// <summary>
    /// 学生类
    /// </summary>
    public class Student
    {
        public int Id { get; set; }
        public int ClassId { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        public void Study()
        {
            Console.WriteLine("自学C#高级课程");
        }
        public void StudyHard()
        {
            Console.WriteLine("努力自学C#高级课程");
        }
    }

    /// <summary>
    /// 班级类
    /// </summary>
    public class Class
    {
        public int Id;
        public string ClassName;
    }

    /// <summary>
    /// 扩展方法:静态类里面的静态方法,第一个参数类型前面加上this
    /// 用途:不修改类,增加方法,用起来方便一些。
    /// 缺陷:如果类内已经有了扩展方法相同的方法,优先调用类内的实例方法(有隐患)。
    /// 指定类型扩展,不要扩展object。
    /// </summary>
    public static class ExtendMethod
    {
        public static void Sing(this Student student)
        {
            Console.WriteLine("Sing a song");
        }

        /// <summary>
        /// null默认是defaultValue,默认是0
        /// </summary>
        /// <param name="iValue"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static int ToInt(this int? iValue, int defaultValue = 0)
        {
            return iValue ?? defaultValue;//如果iValue不为空,返回iValue,否则返回-1。
        }

        /// <summary>
        /// 扩展基类型,导致任何子类都有这个方法,而且可能覆盖方法名相同的方法,非常不推荐扩展object类型
        /// </summary>
        /// <param name="oValue"></param>
        /// <returns></returns>
        public static int Length(this object oValue)
        {
            return oValue == null ? 0 : oValue.ToString().Length;
        }

        /// <summary>
        /// 泛型扩展方法要加约束,否则和扩展object类型效果一样
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        public static void ExtendShow<T>(this T t) where T : Student  //泛型约束
        {
            Console.WriteLine("I am ExtendShow");
        }

        /// <summary>
        /// 扩展方法,只针对Student
        /// </summary>
        /// <param name="source"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static List<Student> CgcWhere(this List<Student> source, Func<Student, bool> func)
        {
            var list = new List<Student>();
            foreach (var item in source)
            {
                if (func.Invoke(item))
                {
                    list.Add(item);
                }
            }
            return list;
        }

        /// <summary>
        /// 泛型扩展方法,可以针对任何类型
        /// </summary>
        /// <param name="source"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static List<T> GenericCgcWhere<T>(this List<T> source, Func<T, bool> func)
        {
            var list = new List<T>();
            foreach (var item in source)
            {
                if (func.Invoke(item))
                {
                    list.Add(item);
                }
            }
            return list;
        }

        /// <summary>
        /// 加上迭代器的扩展方法,按需加载:标准的Linq
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static IEnumerable<T> YieldCgcWhere<T>(this IEnumerable<T> source, Func<T, bool> func)
        {
            if(source==null)
            {
                throw new Exception("source is null");
            }
            if(func==null)
            {
                throw new Exception("func is null");
            }
            foreach (var item in source)
            {
                if (func.Invoke(item))
                {
                    yield return item;
                }
            }
        }
    }
        #endregion
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值