C#-ling实战002-语法糖说明

语法糖

指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。
需要声明的是“语法糖”这个词绝非贬义词,它可以给我们带来方便,是一种便捷的写法,编译器会帮我们做转换,而且可以提高开发编码的效率,在性能上也不会带来损失。

备注:本节只介绍与linq相关的语法糖

更多语法糖介绍:C#十种语法糖

语法糖:Lambda表达式

Lambda表达式是比匿名方法更简洁的一种匿名方法语法

最基本的Lambda表达式语法:
{参数列表}=>{方法体}
例如:
(int x)=>{returm x+1}
说明:
1、参数列表中的参数类型可以是明确类型或推断类型
2、如果是推断类型,则参数的数据类型将由编译器根据上下文自动推断出来

如果参数列表只包含一个推断类型参数时:
参数列表=>{方法体}
前提:x的数据类型可以根据上下文推断出来
 x =>{returm x+1}

如果方法体只包含一条语句时:
{参数列表}=>表达式
{int x} => x+1;

Lambda表达式示例:
1、多参数,推断类型参数列表,表达式方法体
(x,y) => x*y
2、无参数,表达式方法体
() => Console.WriteLine()
3、多参数,推断类型参数列表,多语句方法体,需要使用{}
(x,y) => {Console.WriteLine(x);Console.WriteLine(y)}

Lambda表达式缩写推演
new Func(delegate(string str){return str.Length;});//内置委托
delegate(string str){return str.Length;}//匿名方法
(string str)=>{return str.Length};//Lambda表达式
(str)=>str.Length;//让编译器推断类型
str=>str>Length;//去掉不必要的括弧

 #region Lambda表达式
  
             //标准语法
             MyDelegate my1 = (string name) => { return "Lambda表达式:hello" + name; };
             Console.WriteLine(my1("tom"));
 
            //或者(仅有一个参数) 参数列表只包含一个推断类型参数
            MyDelegate my2 = name => { return "Lambda表达式:hello" + name; };
            Console.WriteLine(my2("tom"));

            //或者(方法体只有一条语句)
            MyDelegate my3 = name => "Lambda表达式:hello" + name;
            Console.WriteLine(my3("tom"));
 
#endregion

语法糖:匿名类和匿名方法

匿名类型
有时候你定义的类只是用来封装一些相关的数据,但并不需要相关联的方法、事件和其他自定义的功能。同时,这个类仅仅在当前的应用程序中使用,而不需要在项目间重用。你所需要的只是一个“临时的”类型,现在来看看这个类的定义
internal class oneClass
{
   //定义若干私有数据成员
   //通过属性来封装每个数据成员
}

构建上面的类虽然说不上有多难,但是如果这个类有很多数据成员的话,那么还是要消耗相当时间的。C#3.0提供了匿名类型来轻松完成这个工作。
现在定义一个匿名对象来表示一个人
var aPeople=new {pName="张三",pAge=26,pSex="男"};
现在我们就可以使用属性语法获取和设置对象的各个变量
aPeople.pAge=29;
Console.WriteLine("{0} is {1}years old",aPeople.pName,aPeople.pAge);
匿名类型的嵌套
    刚刚我们定义了表示一个人的匿名类型,现在我们定义一个表示雇员的嵌套匿名类型:
    var Aemployee=new {
        JoinDate="2012-09-23",
        aPeople=new {pName="张三",pAge=26,pSex="男"},
        title=Manager
    };

匿名类型的限制:
1、匿名类型不支持事件、自定义方法和自定义重写
2、匿名类型是隐式封闭的
3、匿名类型的实例创建只使用默认构造函数
4、匿名类型没有提供可供控制的类名称(使用var定义的)

匿名方法
普通方法定义方式,因为方法的存在是为了复用一段代码,所以一般会给方法取个名字,这个方法的引用就可以通过“方法名”调用
匿名方法:
但是有的方法,不需要复用,仅仅是使用一次就够了,所以不需要方法名,这种方法就叫做匿名方法。
匿名方法必须结合委托使用。(潜在的意思就是:尽管没有方法名了,但方法的指针还是存放了某个委托对象中)
注意:
1、在编译后,会为每个匿名方法创建一个私有的静态方法,然后将此静态方法传给委托对象使用
2、匿名方法编译后会生成委托对象,生成方法,然后把方法装入委托对象,最后赋值给声明的委托变量
3、匿名方法可以省略参数,编译的时候会自动为这个方法按照委托签名的参数添加参数

匿名类:

public class Test
    {
        public static void TestFive()
        {
            //匿名类型:只能使用一次,仅能在当前的项目中使用
            var aPeople = new { pName = "张三", pAge = 26, pAddress = "美国" };
            //嵌套匿名类型
            var aEmployee = new
            {
                JionDate = DateTime.Now,
                Salary = 8000,
                aPeople = new { pName = "张三", pAge = 26, pAddress = "美国" }
            };

            Console.WriteLine(aEmployee.aPeople.pName);//输出:张三

            Console.ReadKey();
        }

        public static void Test()
        {
            //不能使用匿名类型aPeople,aPeople是局部
            Console.WriteLine(aPeople.pName);//错误
        }
    }

匿名方法:

class Program
    {
        /// 
        /// 声明委托
        /// 
        /// 
        delegate void Printer(string s);
        public delegate void PrintEmployee(User u);

        static void Main(string[] args)
        {
            //匿名方法:必须结合委托使用
            Printer p = delegate(string s)
            {
                Console.WriteLine(s);
            };
            //使用匿名方法
            p("Hello World");

            List listUser = new List()
            {
                new User(){Name="张三",Password="1234",Age=12,DeptId="0001"},
                new User(){Name="张四",Password="1234",Age=16,DeptId="0002"},
                new User(){Name="张五",Password="1234",Age=29,DeptId="0003"},
                new User(){Name="张六",Password="1234",Age=18,DeptId="0001"},
                new User(){Name="张七",Password="1234",Age=12,DeptId="0001"}
            };

            //匿名方法只使用一次
            ChangeUserPwd(listUser, delegate(User u) {

                Console.WriteLine(u.Name+"的新密码是:"+u.Password);
            });
            //使用Lambda表达式
            ChangeUserPwd(listUser, u=>
            {
                Console.WriteLine(u.Name + "的新密码是:" + u.Password);
            });
            Console.ReadKey();
        }

        /// 
        /// 批量修改用户的密码并输出修改以后的密码
        /// 
        /// 
        /// 
        public static void ChangeUserPwd(List list, PrintEmployee callback)
        {
            int i = 0;
            foreach (User u in list)
            {
                u.Password = u.Password + i.ToString();
                i += 2;
                callback(u);
            }
        }
    }

语法糖:扩展方法

为什么要有扩展方法,就是为了在不修改源码的情况下,为某个类增加新的方法。
语法:
定义静态类,并添加public的静态方法,第一个参数代表扩展方法的扩展类。它必须放在一个非嵌套、非泛型的静态类中(的静态方法);它至少有一个参数;第一个参数必须附加this关键字;第一个参数不能有任何其他修饰符(out/ref).第一个参数不能是指针类型。
注意:
1、C#只支持扩展方法,不支持扩展属性、扩展事件等;
2、方法名无限制,第一个参数必须带this,表示要扩展的类型;
3、扩展方法的命名空间可以使用namespace System,但不推荐;
4、定义扩展方法的类必须是静态类;
5、扩展方法虽然是public的静态方法,但是生成以后是实例方法,使用时需要先实例化对象,通过对象.方法名进行调用扩展方法;

/// 
    /// 静态类:对Convert进行扩展,增加一个将string转换成int的方法
    /// 
    public static class ConvertExtension
    {
        /// 
        /// 静态方法:this 表示针对this后面的类型进行扩展
        /// 
        /// 
        /// 
        public static int ConvertToInt(this Convert convert,string s)
        {
            int i;
            if (int.TryParse(s, out i))
            {
                return i;
            }
            else
            {
                return 0;
            }
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            //使用扩展方法:扩展方法虽然是public的静态方法,但是生成以后是实例方法,使用时需要先实例化对象,通过对象.方法名进行调用扩展方法
            //扩展方法所在命名空间和使用代码的命名空间必须相同 扩展方法必须是静态类
            Convert convert = new Convert();
            int i= convert.ConvertToInt("abc");

            Console.WriteLine(i);//输出:0

            //方法2
            int j= ConvertExtension.ConvertToInt(convert, "2");
            Console.WriteLine(j);//输出:2

            Console.ReadKey();
        }
    }

语法糖:lambda表达式

Lambda表达式

Lambda表达式是比匿名方法更简洁的一种匿名方法语法

最基本的Lambda表达式语法:
{参数列表}=>{方法体}
例如:
(int x)=>{returm x+1}
说明:
1、参数列表中的参数类型可以是明确类型或推断类型
2、如果是推断类型,则参数的数据类型将由编译器根据上下文自动推断出来

如果参数列表只包含一个推断类型参数时:
参数列表=>{方法体}
前提:x的数据类型可以根据上下文推断出来
 x =>{returm x+1}

如果方法体只包含一条语句时:
{参数列表}=>表达式
{int x} => x+1;

Lambda表达式示例:
1、多参数,推断类型参数列表,表达式方法体
(x,y) => x*y
2、无参数,表达式方法体
() => Console.WriteLine()
3、多参数,推断类型参数列表,多语句方法体,需要使用{}
(x,y) => {Console.WriteLine(x);Console.WriteLine(y)}

Lambda表达式缩写推演
new Func(delegate(string str){return str.Length;});//内置委托
delegate(string str){return str.Length;}//匿名方法
(string str)=>{return str.Length};//Lambda表达式
(str)=>str.Length;//让编译器推断类型
str=>str>Length;//去掉不必要的括弧

#region Lambda表达式

            //标准语法
            MyDelegate my1 = (string name) => { return "Lambda表达式:hello" + name; };
            Console.WriteLine(my1("tom"));

            //或者(仅有一个参数) 参数列表只包含一个推断类型参数
            MyDelegate my2 = name => { return "Lambda表达式:hello" + name; };
            Console.WriteLine(my2("tom"));

            //或者(方法体只有一条语句)
            MyDelegate my3 = name => "Lambda表达式:hello" + name;
            Console.WriteLine(my3("tom"));

            #endregion

语法糖:Linq:语言集成查询

Linq是一组语言特性和API,使得你可以使用统一的方式编写各种查询。查询的对象包括XML、对象集合、SQL Server数据库等等。

Linq to Objects:主要负责对象的查询(本例)

Linq to XML:主要负责XML的查询
Linq to ADO.NET:主要负责数据库的查询

语法糖:Linq标准查询运算符

标准查询运算符:定义在System.Linq.Enumerable类中的50多个为IEnumerable准备的扩展方法,这些方法用来对它操作的集合进行查询筛选。
筛选集合where:需要提供一个带bool返回值的“筛选器”,从而标明集合中某个元素是否应该被返回。
查询投射:返回新对象集合IEnumerable Select()
统计数量int Count()
多条件排序 OrderBy().ThenBy().ThenBy()
集合连接 Join()

Linq查询的两种方式:
1、查询方法方式(Linq标准查询运算符):主要利用System.Linq.Enumerable类中定义的扩展方法和Lambda表达式进行查询
2、查询语句方式(Linq:语言集成查询):一种更接近SQL语法的查询方式

查询语句VS查询方法
1、CLR本身并不理解查询语句,它只理解查询方法
2、编译器负责在编译时将查询语句翻译成查询方法
3、大部分查询方法都有对应的查询语句形式:Select()对应select、OrderBy()对应orderby
4、部分查询方法目前在C#中还没有对应的查询语句,如:Count()和Max()这时只能采用以下替代方案:
   查询方法
   查询语句+查询方法的混合方式

说明:后续会详细说明查询方法方式和查询语句方式

参考:

C#十种语法糖

你可能感兴趣的:(C#-linq,c#,linq)