当前位置:首页 > Windows程序 > 正文

[C#]6.0新特性浅谈

2021-03-27 Windows程序

C#6.0出来也有很长一段时间了,虽然新的特性和语法趋于稳定,但是对于大多数程序猿来说,想在工作中用上C#6.0估计还得等上不短的一段时间。
所以现在再来聊一聊新版本带来的新特性可能也还不算晚吧?

一、nameof关键字

这绝对是整个新版本最让我期待的内容,它给代码重构带来了巨大的便利。
先来看一下它是怎么使用的吧:

string s; Console.WriteLine(nameof(s)); s = nameof(s.Length); Console.WriteLine(nameof(String)); Console.WriteLine(nameof(string.Length)); Console.WriteLine(nameof(string.Substring));

运行结果:

s
String
Length SubString

通过上面的示例,可以看出来以下几点:

1.它不在乎变量是否已经初始化2.它构成了一个运算结果为字符串的(编译时)表达式
3.它可以用于取得类型名,但是nameof(string)是不能通过编译的,小写的string是关键字而不是类型(这一点很值得吐槽。。。)
4.它的括号里面可以直接从类型取得实例属性
5.它可以取得方法名

然后看这段代码的IL:

IL_0000: ldstr "s" IL_0005: call void [mscorlib]System.Console::WriteLine(string) IL_000a: ldstr "String" IL_000f: call void [mscorlib]System.Console::WriteLine(string) IL_0014: ldstr "Length" IL_0019: call void [mscorlib]System.Console::WriteLine(string) IL_001e: ldstr "Substring" IL_0023: call void [mscorlib]System.Console::WriteLine(string) IL_0028: ret

编译后看不到nameof的痕迹,编译器把nameof的运算结果硬编码了,所以说它是一个"编译时运算符"。
适用场景:

1.空引用异常信息构成
2.ToString方法
3.IList数据绑定的列名

主要吐槽一下第三条吧,这是我最近工作里遇到的很闹心的一个事情,什么时候用上了6.0就能彻底解决这个麻烦了。。。
想象一下以前绑定一个自定义类型的List到ListBox吧,要设定DisplayMember和ValueMember的话就只能是硬编码,像是这样:

listBox1.DisplayMember = "ID"; listBox1.ValueMember = "Content";

一旦要对这个绑定类型的属性名称进行更改,工作量简直不敢想象。。。好一点的做法是用一套常量来代替硬编码,但是这样带来的麻烦是还得记着常量名。
不过以后用上了nameof就爽快了,一个Ctrl+R,R通通搞定~

二、[.?]空引用判断操作符

这算是一个用于简洁代码的语法糖吧,个人觉得实用价值一般般。
先看怎么用的吧:

string s = null; s = s?.Substring(1); // s = (s != null ? s.SubString(1) : null); Console.WriteLine(s == null);

第二行代码与第三行被注释掉的部分,在编译过后是完全相等的。
同时也就是说一旦用了[.?],返回值就有可能是null,所以对于原本返回值类型的成员,只能赋值给Nullable<?>了,比如这样:

string s = null; int? i = s?.IndexOf("."); int j = s.IndexOf(".");

至于之后再要用到变量i,很多情况下仍然需要对是否空值进行判断。。。
同时这个语法糖也带来了歧义,比如这样:

object tag = form?.Tag;

由于Form和Tag都是引用类型,都可能为null,如果变量tag是null,这时候是没办法知道到底是form还是Tag返回了null(除非再判断一次。。。)。

三、字符串嵌入值

同样是一个用于简洁代码的语法糖,先看怎么用吧:

int i = 1; Console.WriteLine($"{nameof(i)} + 1 = {i + 1}"); Console.WriteLine($"{i + 1} * {i + 1} = 4");

运行结果:

i + 1 = 2
2 * 2 = 4

然后是IL:

IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: ldstr "{0} + 1 = {1}" IL_0007: ldstr "i" IL_000c: ldloc.0 IL_000d: ldc.i4.1 IL_000e: add IL_000f: box [mscorlib]System.Int32 IL_0014: call string [mscorlib]System.String::Format(string, object, object) IL_0019: call void [mscorlib]System.Console::WriteLine(string) IL_001e: ldstr "{0} * {1} = 4" IL_0023: ldloc.0 IL_0024: ldc.i4.1 IL_0025: add IL_0026: box [mscorlib]System.Int32 IL_002b: ldloc.0 IL_002c: ldc.i4.1 IL_002d: add IL_002e: box [mscorlib]System.Int32 IL_0033: call string [mscorlib]System.String::Format(string, object, object) IL_0038: call void [mscorlib]System.Console::WriteLine(string) IL_003d: ret

可以看出来以下几点:

1.大括号可以用于包裹表达式
2.相同的表达式需要计算两次

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/68409.html