博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
尝尝C#的语法糖(自动属性/匿名方法/Lamda表达式等)-小心蛀牙!
阅读量:6417 次
发布时间:2019-06-23

本文共 4744 字,大约阅读时间需要 15 分钟。

-语法糖意指那些没有给计算机语言添加新功能,而只是对人类来说更“sweet”的语法,意在使得编程风格更易读。C#2.0,3.0发布的新特性,除了泛型不是语法糖,其他所有的新特性几乎都是语法糖。

-但初学者往往因为不了解这些语法糖,从而在阅读代码的时候,难以理解其真正的运作方式。最著名的莫过于Lamda表达式,第一次看到它,很多人都会顶个大问号把。。。

-文章前面会伴随一些让人看着想吐槽的代码,请大家自行河蟹。然后我们会介绍一些语法糖来润色一下,方便初学者们知道这些语法糖的原始意义。

  我们来做一个List<T>类的练习。我会写一个很蛋疼的例子(尽量不用语法糖,当然这很难避免)。首先我定义了一个学生类

public class Student{    private string num;    public string Num { get { return num; } }    private string name;    public string Name { get { return Name; } }    public Student(string num, string name)    {        this.num = num;        this.name = name;    }    public override string ToString()    {        return num + ":" + name;    }}

  现在练习下List<T>的FindAll()方法,它的声明如下

public T FindAll(Predicate
match)

  FindAll方法把Predicate<T>作为参数,Predicate<T>是一个委托,它引用一个谓词方法-返回布尔值的方法。如果谓词返回true,表示有一个匹配。

  所以我写了一个FindStudent类来定义谓词。这个方法用要搜索的学生的学号来初始化,FindPredicate()接收一个student对象,比较student对象的学号与构造函数中设置的学号,返回true or false。

public class FindStudent  //修正于2010/4/20 感谢 Terry_Huang和 Jack Afa指正    {        private string num name;        public FindStudent(string num Name)        {            this.num = num;             this.name = Name;        }        public bool FindPredicate(Student student)        {            return student.Name == name;        }    }

  最后在一个控制台程序里搜索名字叫John的学生。

class Program    {        static void Main(string[] args)        {            List
Students = new List
(); Students.Add(new Student("001", "John")); Students.Add(new Student("002", "Marry")); Students.Add(new Student("003", "John")); FindStudent finder = new FindStudent("John"); foreach (var student in Students.FindAll(new Predicate
(finder.FindPredicate))) { Console.Write(student); } } }

  有没有人看到这已经扛不住了呢,特别是对FindStudent类和FindAll的冗长的用法?

  下面我们来一点一点的润色把。

  甜死你1号-自动属性:只需在定义一个类时指定属性名,C#3.0编译器将自动实现相应的内部的private变量,并自动生成set访问器和get访问器。

  甜死你2号-对象初始值设定项:在自动属性的前提下,在创建对象时可以对任何可访问的属性或字段赋值,而不需要显示的调用构造函数。

  基于这两个特性,我们来修改一下Student类:

public class Student{    public string Num { get; set; }    public string Name { get;set; }    public override string ToString()    {        return Num + ":" + Name;    }}

 

  自动属性会自动生成私有变量,不需要显示的声明,并且可以直接通过对象初始值设定项对可访问的属性和字段赋值,构造函数也不是必须的。呃,是不是清爽多了。

  甜死你3号-匿名方法 : 我们之前必须首先声明方法后才能在委托中使用,C#2.0引入匿名方法,可以delegate{ //dosomething}的形式以一种“内联”的方式来编写方法代码,将代码直接与委托实例相关联,从而使得委托实例化的工作更加直观和方便。

  有些时候我们需要临时保存一些运算的中间结果,我们常常会去声明一个新的类型,以方便保存这些中间结果。表面上 看起来这很正常,而细想之后就会发现,这个新类型只服务于这个函数,其它地方都不会再使用它了,就为这一个函数而去定义一个新的类型,确实有些麻烦,比如FindStudent类。

  有了匿名方法FindStudent类已经没有存在的意义了(大快人心?),因为自动属性的关系,我们可以直接访问属性,并且用匿名方法来代替谓词。

  插播广告:

  甜死你4号-集合初始值设定项:我们除了可以像初始化数组一样,初始化对象之外,同样对于集合也可以不用再重复的Add来增加集合项了,我们来看新的Main函数:

static void Main(string[] args)        {            List
Students = new List
() { new Student(){ Num="001", Name="John"},//使用对象初始值设定项初始化对象,代替构造函数 new Student(){ Num="002", Name="Marry"}, new Student(){ Num="003", Name="John"} };//使用集合初始值设定项初始化集合,不用重复调用Add方法 foreach (var student in Students.FindAll(delegate(Student student) { return student.Name == "John"; }))//使用匿名方法完成FindStudent类的功能 { Console.WriteLine(student); } Console.ReadKey(); }

  是不是看着顺眼多了。不过foreach这句还是有点不顺眼。肿么办,我们只好开大招了。

  甜死你终结者号-Lamda表达式:它是升级版的匿名方法,其作用是简化匿名方法的写法。写法(形参列表)=>{函数体}

  delegate(Student student) { return student.Name == "John"; }这个匿名方法为例,我们的参数就只有student一个,形参我们就使用s代替。

  Lamda表达式就是 s=>s.Name=="John"。

  顺便我们用一下List<T>的ForEach方法。

  又一条广告: 

  甜死你路人号-匿名类型: 使用var关键字来进行类型声明,而不需要显示的声明类型,具体的类型将由编译器来推断。

  最终的Main函数就是:

static void Main(string[] args)        {            List
Students = new List
() { new Student(){ Num="001", Name="John"},//使用对象初始值设定项初始化对象,代替构造函数 new Student(){ Num="002", Name="Marry"}, new Student(){ Num="003", Name="John"} };//使用集合初始值设定项初始化集合,不用重复调用Add方法 var John = Students.FindAll(s => s.Name == "John");//使用var声明匿名类型,其实John是个List
John.ForEach(j => Console.WriteLine(j));//使用Lamda表达式 Console.ReadKey(); }

  这样的代码看着就很舒服了。

  当然语法糖还有很多,如文章开头所说,C#的新特性大多是语法糖。当然还有一些其他的语法糖,比如三元运算符Test?expression1:expression2就有一个语法糖,写作

  expression1??expression2   2选1,expression1为null则执行expression2。反之执行expression1。

  欢迎大家补充,这里就不多做介绍了。

  --------------------------------------------我是分割线------------------------------------------------

  语法糖能够增加程序的可读性,但凡事都有两面性。比如你需要在属性的get方法中写一些逻辑,显然自动属性就不适用了。所以不必强求。

  咱别硬吃把牙吃坏了。。。

 

 

转载于:https://www.cnblogs.com/John-Connor/archive/2012/04/16/2446957.html

你可能感兴趣的文章
C语言中二维字符数组的定义和初始化
查看>>
源程序出现各种奇怪的符号P
查看>>
【svn】 linux svn 强制提交注释
查看>>
P6 EPPM R16.1安装与配置指南(一)
查看>>
sys模块 和os模块
查看>>
Redhat修改主机名_Red hat怎么永久修改主机名hostname(转)
查看>>
javascript运算符——条件、逗号、赋值、()和void运算符
查看>>
网络包
查看>>
dll版本冲突的解决方法
查看>>
卡方检验(Chi-square test/Chi-Square Goodness-of-Fit Test)
查看>>
在.jsp中非表单请求action的几种方式总结
查看>>
爬取熊猫TV,javascript,selenium,模拟点击
查看>>
厦门大学2016年高等代数考研试题参考解答
查看>>
[转] C# 获取程序运行目录
查看>>
c++ 基于wincrypt的DES CBC模式加解密
查看>>
Logic Bist Arch
查看>>
程序员常用工具软件 总结
查看>>
Codeforces Round #369 (Div. 2) A. Bus to Udayland 水题
查看>>
C#预处理器指令【转】
查看>>
adb上使用cp/mv命令的替代方法(failed on '***' - Cross-device link解决方法)
查看>>