目录

一、C#语法糖大汇总

1. 经过简化的Property
2. 经过两次变异的委托写法
3. 集合类的声明
4. 集合类各个项的操作
5. using == try finally
6. 可爱的var
7. 问号的演变
8. 类型实例化的语法糖
9. 传说中的扩展方法
10.使用匿名类

二、C#之6.0语法糖剖析

2.1 自动属性默认初始化
2.2 自动只读属性默认初始化
2.3 表达式为主体的函数
2.4 表达式为主体的属性(赋值)
2.5 静态类导入
2.6 Null条件运算符
2.7 字符串格式化
2.8 索引初始化
2.9 异常过滤器when
2.10 catch和finally代码块内的Await
2.11 nameof表达式
2.12 扩展方法
总结


一、C#语法糖大汇总

首先需要声明的是“语法糖”这个词绝非贬义词,它可以给我带来方便,是一种便捷的写法,编译器会帮我们做转换;而且可以提高开发编码的效率,在性能上也不会带来损失。这让java开发人员羡慕不已,呵呵。

1.  经过简化的Property

早些时候我们这样声明Property

private string _myName;
public string MyName
{get { return _myName; }set { _myName = value; }
}

千篇一律的这样声明,没有多大意义,于是C#的设计人员将这个千篇一律的工作交给了编译器帮我们做了,我们现在可以这样声明

public string MyName { get; set; }

当然他不会牺牲灵活性,我们可以单独给get或者set设定访问限制符,例如

public string MyName { get; protected internal set; }

2.  经过两次变异的委托写法

在.net 1.1时我们不得不声明方法后才在委托中使用,在.net 2.0之后我们可以使用匿名委托,他不单可以简化写法,还可以在匿名委托中访问范围内的变量;再后来拉姆达表达式来了,写法就更简便了。

class MyClass
{public delegate void DoSomething(int a);//定义方法委托private void DoIt(int a) {Console.WriteLine(a);}private void HowtoDo(DoSomething doMethod,int a) {doMethod(a);}public static void Main(string[] args) {MyClass mc = new MyClass();//调用定义的方法委托mc.HowtoDo(new DoSomething(mc.DoIt), 10);int x = 10;//使用匿名委托mc.HowtoDo(delegate(int a){Console.WriteLine(a + x);},10);//使用lamda表达式mc.HowtoDo(a=>Console.WriteLine(a+x),10);Console.ReadLine();}
}

3.  集合类的声明

//之前我们声明一个List并给list赋初始值,必须得这么写:
List<string> list = new List<string>();
list.Add("a一");
list.Add("b二");
list.Add("c三");//现在不需要了,直接写就可以了
List<string> list = new List<string> {"def","OK"};

4.  集合类各个项的操作

//我们为了逐个处理集合中的项,需要这么写:
foreach (string item in list)
{Console.WriteLine(item);
}//现在不需要了,这样就可以了
list.ForEach(a => Console.WriteLine(a));

5.  using == try finally

为了在使用完毕时释放资源,我们经常要用using,using实质上就是try fiannaly的一个语法糖而已。例如

StreamWriter sw = null;
try
{sw = new StreamWriter("d:\abc.txt");sw.WriteLine("test");
}
finally {if(sw!= null) sw.Dispose();
}//上面的代码可以简化为:
using (var sw = new StreamWriter("d:\abc.txt")) {sw.WriteLine("test");
}

6.  可爱的var

var的意义时不必写声明的类型,编译器会根据后面对var的赋值判断它的类型,var的类型一旦确认就不能再改变,它只能作为局部变量使用,不能用做字段也不能用做参数声明。

var writer = new StreamWriter(path);for(var i=0;i<100;i++){}

7.  问号的演变

老掉牙的一个问号+冒号

var b = 3;
var a = b > 9?b.ToString():”0”+b;

新宝宝两个问号 ??,它表示左边的变量如果为null则值为右边的变量,否则就是左边的变量值

string a = null;
var b = a??””;

8.  类型实例化的语法糖

public class Abc
{public int ID { get; set; }public string Name { get; set; }public string Url { get; set; }
}//我们没有为上面的类声明构造函数,但是我们可以像下面的形式来实例化它
public static void Main(string[] args) {var abc = new Abc{ID=1,Name="yukaizhao",Url="http://yukaizhao.cnblogs.com/"};}

9.  传说中的扩展方法

在c#3.5时引入了扩展方法,我们可以在不修改类源码的情况下给类增加实例方法,这个很有意义。它的实质也是一种语法糖的实现
例如我们给String类扩展一个IsNumber的方法:

public static class StringExt {static private Regex regexNumber = new Regex("\\d+");static public bool IsNumber(this string input){if (string.IsNullOrEmpty(input)){return false;}return regexNumber.IsMatch(input);}
}//我们可以在String实例上调用这个方法了
var abc = “123”;
var isNumber = abs.IsNumber();

10.使用匿名类

var a = new {ID = 1,Name=”yukaizhao”,BlogUrl=”http://www.cnblogs.com/yukaizhao/”
};

匿名类在linq to sql或者entity framework中返回查询数据时很好用。


C#6

静态类导入using static System.Console;

11. NULL条件运算符

//使用代码
Customer customer = new Customer();
string name = customer?.Name;//编译代码
Customer customer = new Customer();
if (customer != null)
{string name = customer.Name;
}

也可以和??组合起来使用

if (customer?.Face()??false)

还可以两个一起组合来使用

int? contactNameLen = contact?.Name?.Length; 

这个语法糖的目的是在对象使用前检查是否为null。如果对象为空,则赋值给变量为空值,所以例子中需要一个可以为空的int类型、即int?。如果对象不为空,则调用对象的成员取值,并赋值给变量。

12. 字符串格式化

String.Format有些不方便的地方是:必须输入"String.Format",使用{0}占位符、必须顺序来格式化、这点容易出错。

var contactInfo = string.Format("Id:{0} Name:{1} EmailAddr:{2} PhoneNum:{3}", contact.Id, contact.Name, contact.EmailAddress, contact.PhoneNum);//新的语法
var contactInfo2 = $"Id:{contact.Id} Name:{contact.Name} EmailAddr:{contact.EmailAddress} PhoneNum:{contact.PhoneNum}";//新格式化方式还支持任何表达式的直接赋值:
var contactInfo = $"Id:{contact.Id} Name:{(contact.Name.Length == 0 ? "Frank" : contact.Name)} EmailAddr:{contact.EmailAddress} PhoneNum:{contact.PhoneNum}";


二、C#之6.0语法糖剖析

2.1 自动属性默认初始化

//使用方法:
public string Name { get; set; } = "hello world";//为了便于理解使用2.0语法展示,编译器生成代码如下:
public class Customer
{[CompilerGenerated]
private string kBackingField = "hello world";
public Customer()
{ this.kBackingField = "hello world";
}public string Name
{[CompilerGenerated]get{return this.<Name>k__BackingField;}[CompilerGenerated]set{this.<Name>k__BackingField = value;}
}
}
//从生成代码中可以看出编译器是在实例构造函数时,初始化属性信息的。

2.2 自动只读属性默认初始化

//使用方法:
public string Name1 { get; } = "hello world";//编译器生成代码如下:
[CompilerGenerated]
private readonly string kBackingField;
public Customer()
{this.kBackingField = "hello world";
}
public string Name1
{[CompilerGenerated] get { return this.k__BackingField; }
}
//由于初始化默认值实在构造函数中赋值的,所以跟属性只读没关系。

2.3 表达式为主体的函数

//使用方法:
Body Get(int x, int y) => new Body(1 + x, 2 + y);//编译器生成如下:
private Program.Body Get(int x, int y)
{return new Program.Body(1 + x, 2 + y);
}
//简化了单行方法的编写,省去写大括号的功夫。//同时支持没有返回值的写法:
void OutPut(int x, int y) => Console.WriteLine("hello world");//也支持异步函数的编写:
async void OutPut(int x, int y) => await new Task(() => Console.WriteLine("hello wolrd"));

2.4 表达式为主体的属性(赋值)

//使用方法:
public string Name2 => "hello world";//编译器生成代码如下:
public string Name2
{ get { return "mushroomsir"; }
}
//编译器只生成了个只读属性。

2.5 静态类导入

//这个特性可以一次性导入某类型的所有静态成员,使静态成员在后面的代码中没有类型限制直接使用,像使用本类型下面的静态方法一样。
using static System.Console;
class Program
{ static void Main(string[] args) {WriteLine("hello wolrd"); }
}//编译器生成代码如下:
private static void Main(string[] args)
{Console.WriteLine("hello wolrd");
}
//省去了类型名称的重复编写。

2.6 Null条件运算符

//使用方法:
Customer customer = new Customer();
string name3 = customer?.Name;//等同于:
Customer customer = new Customer();
if (customer1 != null)
{string name = customer1.Name;
}//可以和??组合起来使用:
if (customer?.Face2()??false)//还可以2个一起用:
int? Length = customer?.Name?.Length;//也可以方法调用:
customer?.Face();

这个语法糖的目的是在对象使用前检查是否为null。如果对象为空,则赋值给变量为空值,所以例子中需要一个可以为空的int类型、即int?。

如果对象不为空,则调用对象的成员取值,并赋值给变量。

2.7 字符串格式化

//String.Format有些不方便的地方是:必须输入"String.Format",使用{0}占位符、必须顺序来格式化、这点容易出错。
var s = String.Format("{0} is {1} year {{s}} old", p.Name, p.Age);//新的语法糖使用起来相对更轻松些:
var s = $"{p.Name} is {p.Age} year{{s}} old";//编译器生成如下,和之前没有区别:
var s = String.Format("{0} is {1} year{{s}} old", p.Name, p.Age);//有趣的是,新格式化方式还支持任何表达式的直接赋值:
var s = $"{p.Name} is {p.Age} year{(p.Age == 1 ? "" : "s")} old";

2.8 索引初始化

//List虽然这样写可以编译通过,但是会抛异常的,使用方法:
var numbers = new List<string> { [7] = "seven", [9] = "nine", [13] = "thirteen" };//编译器生成代码如下:
List list = new List();
list[7] = "seven";
list[9] = "nine";
list[13] = "thirteen";
//Dictionary可以执行,因为二者内部索引机制不一样:
var numbers = new Dictionary<int, string> {[7] = "seven",[9] = "nine",[13] = "thirteen" };//编译器生成代码:Dictionary<int, string> dictionary2 = new Dictionary<int, string>();dictionary2[7] = "seven";dictionary2[9] = "nine";dictionary2[13] = "thirteen";Dictionary<int, string> dictionary = dictionary2;

2.9 异常过滤器when

//使用方法:
try
{ throw new ArgumentException("string error");
}
catch (ArgumentException e) when (myfilter(e))
{ Console.WriteLine(e.Message);
}static bool myfilter(ArgumentException e)
{ return false;
}

When语法作用是:在进入到catch之前、验证when括号里myfilter方法返回的bool,如果返回true继续运行,false不走catch直接抛出异常。

使用这个filter可以更好的判断一个错误是继续处理还是重新抛出去。按照以前的做法,在catch块内如需再次抛出去,需要重新throw出去,这时的错误源是捕捉后在抛的,而不是原先的,有了when语法就可以直接定位到错误源。

2.10 catch和finally代码块内的Await

Await异步处理是在c#5.0提出的,但不能在catch和finally代码块内使用,这次在C#6.0更新上支持了。

使用方法:

   async void Solve(){try{await HttpMethodAsync();}catch (ArgumentException e){await HttpMethodAsync();}finally{await HttpMethodAsync();}}

编译器把catch和finally的await生成到状态机里面的MoveNext()里面。原来里面只有 TaskAwaiter,现在多了2个。状态机里面的代码和原先的一样,只是更复杂了下,有兴趣的童鞋可以先看下Async、Await剖析再去深究。

2.11 nameof表达式

//使用方法:
string name = "";
Console.WriteLine(nameof(name));
//控制台输出 "name"。

有时候会需要程序中一些成员的字符串名称,比如抛出ArgumentNullException异常的时候,想知道ArgumentNullException类型的字符串名称,这时候就可以用nameof获取字符

串“ArgumentNullException”。现在做法都是手动复制一下,但重构改名的时候容易忘记变更字符串,使用nameof就可以避免了。

//当如下使用的时候,编译器会只取最后的ZipCode。
nameof(person.Address.ZipCode)//编译器生成如下代码:
Console.WriteLine("name");

2.12 扩展方法

    using static System.Linq.Enumerable; //引入类型,而不是命名空间class Program{static void Main(){var range = Range(5, 17);                // Ok: 不是扩展方法var odd = Where(range, i => i % 2 == 1); // Error, 不在全局作用域里var even = range.Where(i => i % 2 == 0); // Ok
        }}

首先Enumerable是个静态类,里面是各种扩展方法,比如range。static的作用是把类型的静态成员一次性导入,rang虽然是静态方法,但不能导入,比如where。

因为扩展方法虽然是一个静态方法,但是语法规定它作为一个实例方法使用(打点),所以不能在全局作用域里当静态方法用,因此var odd = Where(range, i => i % 2 == 1)是错误的。

但是static却能把类型的扩展方法作为扩展方法本身角色的功能导入进去,所以var even = range.Where(i => i % 2 == 0)是ok的。

这里可能稍微有点绕,lz尽量写清楚,static新用法有2个功能:

把静态成员导入,但扩展方法比较特殊、排除在外。这时static是c# 6.0的新功能。
等同于把扩展方法的命名空间导入,所以在集合上可以打点调用扩展方法。这是之前就有的功能,而不是把扩展方法转成单纯的静态方法导入使用。

总结

看到园子里有介绍的文章,一时来兴趣了,下班后安装个社区版就研究分享下。 虽然微软一直出新东西,但都是由下至上迭代的,所以学习起来是非常快的。

转载于:https://www.cnblogs.com/zhaoshujie/p/9594646.html

C#语法糖(Csharp Syntactic sugar)相关推荐

  1. 什么是语法糖(Syntactic sugar)?

    大学时没选修编译原理这门课,不知道什么是语法糖,最近看React的官方文档才接触语法糖的概念,简单查了下资料记录下,以下是来自百度百科的解释: 语法糖(Syntactic sugar),也译为糖衣语法 ...

  2. 语法糖(Syntactic sugar)

    语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有 ...

  3. 语法糖(Syntactic sugar)/ 语法盐(syntactic salt)

    语法糖 语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·蘭丁发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用.语法糖 ...

  4. C#语法糖(Csharp Syntactic sugar)大汇总

    首先需要声明的是"语法糖"这个词绝非贬义词,它可以给我带来方便,是一种便捷的写法,编译器会帮我们做转换:而且可以提高开发编码的效率,在性能上也不会带来损失.这让java开发人员羡慕 ...

  5. 语法糖 Syntactic sugar: 复杂代码的等价简洁替代

    语法糖(Syntactic sugar) 在不改变代码所在位置.语法结构的前提下,实现了运行时的等价代码更简洁流畅,代码更语义自然,可读性高 写着爽,看着爽,就像吃了糖,效率高,错误少 例: 最基本的 ...

  6. Java 中的语法糖 (Syntactic Sugar)

    语法糖(Syntactic Sugar),也叫糖衣语法,是英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语.指的是,在计算机语言中添加某种语法,这种语法能使程序员更方便 ...

  7. Java 中的语法糖,真甜。

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 我们在日常开发中经常会使用到诸如泛型.自动拆箱和装箱.内部 ...

  8. Jvm 系列(十一)Java 语法糖背后的真相

    语法糖(Syntactic Sugar),也叫糖衣语法,是英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语.指的是,在计算机语言中添加某种语法,这些语法糖虽然不会对语言 ...

  9. Java的12个语法糖【转】

    本文转载自公众号  Hollis 原创: 会反编译的 Hollis 侵权删 本文从 Java 编译原理角度,深入字节码及 class 文件,抽丝剥茧,了解 Java 中的语法糖原理及用法,帮助大家在学 ...

  10. 几个有趣的名词--语法糖、语法盐等

    今天看<Java NIO>,里边出现"语法糖"这一名词,觉得挺有趣就问google,结果出来连带了其他几个类似名词,这里仅作整理. 语法糖 语法糖(Syntactic ...

最新文章

  1. Swing如何正确的处理界面中的线程(EDT)
  2. python中字典统计成绩合_Python统计字典中的项
  3. python处理表格数据-基于Python快速处理PDF表格数据
  4. 招商银行的软件BUG
  5. 电除尘原理计算机机箱,高炉煤气布袋除尘器计算机监控系统
  6. DreamWeaver连接Tomcat用以编辑和测试JSP
  7. labuladong 的算法小抄_来自GitHub 68.8k star的硬核算法教程
  8. Go2Shell 已无法使用
  9. COGS182 [USACO Jan07] 均衡队形[RMQ]
  10. Python GUI设计 PythonWx
  11. 我的世界pc正版好玩的服务器,都来看看好玩的服务器
  12. url 获取 geoserver 中对应的style
  13. 使用 MyEclipse远程调试 Java 应用程序
  14. LCD1602中文资料
  15. 明日之后服务器维护到几点,明日之后:凌晨三点停机维护,优化排队体验,百万阴兵要撤退了?...
  16. 【系统分析师之路】第七章 复盘系统设计(业务流程建模)
  17. 数据库一条insert插入多条记录
  18. 银河系创投徐芳:专注B2B这片热土,燃起产业新势能 | To B 50+
  19. Java没有友联(函数)这个概念怎么办?
  20. 哔哩哔哩 2019校园招聘 开发工程师-2018.09.21

热门文章

  1. 电脑文件被杀毒软件误删了怎么恢复?
  2. xctf攻防世界 REVERSE 高手进阶区 re2-cpp-is-awesome
  3. 曲苑杂坛--清除维护计划产生的日志文件
  4. 删除用户账户|win7系统怎么删除用户账户
  5. CPU飙高系统反应慢怎么排查?
  6. [Place 30-58] IO placement is infeasible. Number of unplaced terminals (1) is greate
  7. 7个必收藏的免商用无版权的高清图片网站
  8. python实现学生座位表排表
  9. 布丰投针实验 MATLAB仿真 以及报告
  10. (2019)基于传感器融合的机会主义占用计数估计:一个案例研究