第1章 C#和.NET Framework简介

1.6 CLR 和 .NET Framework

.NET Framework 由 CLR 和大量程序库组成。这些程序库核心库应用库组成,应用库依赖于核心库。下图是这些程序库的可视化概况:

1.8 C# 简史

思维导图
mindmap
第1章 C#和.NET Framework简介
C#7.0
数字字面量改进
输出变量<br/>及参数忽略
模式
局部方法
更多表达式体<br>成员
Deconstruct
ValueTuple
throw表达式
C#6.0
null条件运算符
表达式体函数
属性初始化器
索引初始化器
字符串插值
异常过滤器
using static
nameof
C#5.0
async
await

1.8.1 C#7.0 新特性

(C#7.0 随 Visual Studio 2017 发布。)

1.8.1.1 数字字面量的改进

C#7 中,数字字面量可以使用下划线来改善可读性,它们称为数字分隔符而被编译器忽略:

int million = 1_000_000;

二进制字面量可以使用 0b 前缀进行标识:

var b = 0b1010_1011_1100_1110_1111;

1.8.1.2 输出变量及参数忽略

C#7 中,调用含有 out 参数的方法将更加容易。首先,可以非常自然地声明输出变量:

bool successful = int.TryParse("123", out int result);
Console.WriteLine(result);

当调用含有多个 out 参数的方法时,可以使用下划线字符忽略你不关心的参数:

SomeBigMethod(out _, out _, out _, out int x, out _, out _, out _);
Console.WriteLine(x);

1.8.1.3 模式

is 运算符可以自然地引入变量,称为模式变量:

void Foo(object x){
if(x is string s)
Console.WriteLine(s.Length);
}

switch 语句同样支持模式,此时 case 子句对应的是类型而非常量;可以使用 when 子句来指定一个判断条件;或是直接选择 null:

object x = null;
switch (x)
{
case int i:
Console.WriteLine("It's an int!");
break;
case string s:
Console.WriteLine(s.Length);
break;
case bool b when b == true:
Console.WriteLine("True");
break;
case null:
Console.WriteLine("Nothing");
break;
}

1.8.1.4 局部方法

局部方法是声明在其他函数内部的方法

void WriteCubes()
{
Console.WriteLine(Cube(3));
Console.WriteLine(Cube(4));
Console.WriteLine(Cube(5)); int Cube(int value) => value * value * value;
}

局部方法仅仅在其包含函数内可见,它们可以像 Lambda 表达式那样捕获局部变量

1.8.1.5 更多的表达式体成员

C#6 引人了以“胖箭头”语法表示的表达式体的方法只读属性运算符以及索引器。而 C#7 更将其扩展到了构造函数读/写属性终结器中:

public class Person
{
string name; public Person (string name) => Name name; public string Name
{
get => name;j
set => name = value ?? "";
} ~Person() => Console.WriteLine ("finalize");
}

1.8.1.6 解构器

解构方法允许你将一个对象的属性或字段“解构”到一组变量中。这通常是通过在类型中定义一个名为 ​Deconstruct​ ​的方法来实现,该方法以 out 参数的形式输出多个值。

从 C#7.0 开始,这个特性被引入,允许开发者轻松地从对象中提取数据。这在元组的使用中特别有用,因为你可以在一个单独的语句中从对象中提取多个字段或属性:

var joe = new Person("Joe Bloggs");

// 使用解构方法将Person对象的属性解构到两个变量中
var (first, last) = joe;
Console.WriteLine(first); // Joe
Console.WriteLine(last); //Bloggs public class Person
{
public string name; public Person(string name){
this.name = name;
} // 解构方法
public void Deconstruct(out string firstName, out string lastName)
{
int spacePos = name.IndexOf(' ');
firstName = name.Substring(0, spacePos);
lastName = name.Substring(spacePos + 1);
}
}

1.8.1.7 元组

C#7 允许显式定义元组,新元组实质是 System.ValueTuple<...>​ 泛型结构的语法糖:

var bb = ("Bob", 23);
Console.WriteLine(bob.Item1);
Console.WriteLine(bob.Item2);

元组可以做到:

  1. 对元素进行命名
  2. 使用元组做返回值,而非out参数
  3. 隐式支持解构模式

元素进行命名

var tuple = (Name:"Bob", Age:23);
Console.WriteLine(tuple.Name);
Console.WriteLine(tuple.Age);

使用元组做返回值,而非out参数

var pos = GetFilePosition();
Console.WriteLine(pos.row);
Console.WriteLine(pos.column); static (int row, int column) GetFilePosition() => (3, 10);

隐式支持解构模式

元组隐式地支持解构模式,因此很容易解构为若干独立的变量,上述代码可以改成:

var (row, column) = GetFilePosition();
Console.WriteLine(row);
Console.WriteLine(column); (int row2, int column2) = GetFilePosition();
Console.WriteLine(row2);
Console.WriteLine(column2);

1.8.1.8 throw 表达式

在 C#7 之前,throw 一直是一个语句(Statement)。现在它也可以作为表达式(Expression)出现在表达式体函数中:

public string Foo() => throw new NotImplementedException();

throw 表达式也可以出现在三目运算符中:

string Capitalize(string value) =>
value == null ? throw new ArgumentException("value") :
value == "" ? "" :
char.ToUpper(value[0]) + value.Substring(1);

1.8.2 C#6.0 新特性

(C#6.0 随Visual Studio 2015发布)

1.8.2.1 null 条件运算符(Elvis)

null 条件运算符(参见2.10 null 运算符)可以避免在调用方法或访问类型的成员之前显式地编写用于 null 判断的语句。在以下示例中,result 将会为 null 而不会抛​​NullReferenceException​​:

StringBuilder sb = null
string result = sb?.ToString();

1.8.2.2 表达式体函数(expression-bodied function)

参见3.1.2.1 表达式体方法(C#6),可以以Lambda表达式的形式书写仅仅包含一个表达式的方法属性运算符以及索引器,使代码更加简短:

public int TimesTwo(int) => x * 2;
public string SomeProperty => "Property value";

1.8.2.3 属性初始化器(property initializer)

参见3.1.4 对象初始化器,可以对自动属性进行初始赋值:

public DateTime TimeCreated { get; set; } = DateTime.Now;

这种初始化也支持只读属性:

public DateTime TimeCreated { get; } = DateTime.Now;

1.8.2.4 索引初始化器(index initializer)

参见4.6.2 集合的初始化器,可以一次性初始化具有索引器的任意类型:

var dict = new Dictionary<int, string>()
{
[3] = "three",
[10] = "ten"
};

1.8.2.5 字符串插值(string interploation)

参见2.6.2.2 字符串插值(C#6),简化了string.Format​:

string s = $"It is {DateTime.Now.DayOfWeek} today";

1.8.2.6 异常过滤器(exception filters)

参见异常筛选器(C#6),可以在catch块上再添加一个条件:

string html;
try
{
html = new WebClient().DownloadString("http://asef");
}
catch(WebException ex) when(ex.Status == WebExceptionStatus.Timeout)
{
...
}

1.8.2.7 using static

参见2.12.2 using static 指令(C#6),可以引入一个类型的所有静态成员,这样就可以不用书写类型而直接使用这些成员:

using static System.Console;
...
WriteLine("Hello, world");

1.8.2.8 nameof

参见3.1.13 nameof 运算符(C#6)nameof​ 运算符返回变量、类型或其他符号的名称,这样在vs中可以避免重命名造成不一致的代码:

int capacity = 123;
string x = nameof(capacity); // x是"capacity"
string y = nameof(Uri.Host); // y是"Host"

1.8.3 C#5.0 新特性

C#5.0最大的新特性是通过两个关键字,async和await,支持异步功能(asynchronous function)。异步功能支持异步延续(asynchronous continuation),从而简化响应式和线程安全的富客户端应用程序的编写。它还有利于编写高并发和高效的I/O密集型应用程序,而不需要为每一个操作绑定一个线程资源。

1.8.4 C#4.0 新特性

C#4.0 增加的新特性有:

  • 动态绑定
  • 可选参数和命名参数
  • 用泛型接口和委托实现类型变化
  • 改进COM互操作性

1.8.5 C#3.0 新特性

  • LINQ(Language Integrated Query)
  • 隐式类型局部变量(var)
  • 匿名类型(用于LINQ查询结果的输出)
  • 对象初始化器
  • Lambda表达式
  • 扩展方法
  • 查询表达式
  • 表达式树

上述内容都是为LINQ服务的,除此还添加了:

  • 自动化属性
  • 分部方法(Partial Method)

1.8.6 C#2.0 新特性

  • 泛型

    泛型需要在运行时仍能确保类型的正确性,因此引入了CLR2.0

  • 可空类型(nullable type)

  • 迭代器

  • 匿名方法(Lambda表达式的前身)

上述方法为 C#3 的LINQ铺平了道路。此外,还有:

  • 分布类
  • 静态类
  • 命名空间别名
  • 友元程序集
  • 支持定长缓冲区

第1章 C#和.NET Framework简介的更多相关文章

  1. Android Framework 简介

    Android Framework 简介 简介 之前的研究太偏向应用层功能实现了,很多原理不了解没有详记,结果被很多公司技术人员鄙视了,为了减少自己的短板,重新复习了一遍C++.java.Androi ...

  2. Rest Framework简介 和 RESTful API 设计指南

    使用Django Rest Framework之前我们要先知道,它是什么,能干什么用? Django Rest Framework 是一个强大且灵活的工具包,用以构建Web API 为什么要使用Res ...

  3. 【Robot Framework】---- Robot Framework简介、特点、RIDE

    Robot Framework简介.特点.RIDE 一.简介.特点. Robot Framework是一款python编写的功能自动化测试框架.具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型 ...

  4. Django Rest Framework 简介及 初步使用

    使用Django Rest Framework之前我们要先知道,它是什么,能干什么用? Django Rest Framework 是一个强大且灵活的工具包,用以构建Web API 为什么要使用Res ...

  5. 第1章 分布式系统概念与ZooKeeper简介

    ZooKeeper分布式专题与Dubbo微服务入门 第1章 分布式系统概念与ZooKeeper简介 1-1 zookeeper简介 1-2 什么是分布式系统 略 1-3 分布式系统的瓶颈以及zk的相关 ...

  6. 05.DRF-Django REST framework 简介

    一.明确REST接口开发的核心任务 分析一下上节的案例,可以发现,在开发REST API接口时,视图中做的最主要有三件事: 将请求的数据(如JSON格式)转换为模型类对象 操作数据库 将模型类对象转换 ...

  7. 第一篇:Entity Framework 简介

    先从ORM说起吧,很多年前,由于.NET的开源组件不像现在这样发达,更别说一个开源的ORM框架,出于项目需要,以及当时OOP兴起(总不至于,在项目里面全是SQL语句),就自己开始写ORM框架.要开发O ...

  8. SharePoint Framework 简介

    作者:陈希章 发表于 2017年12月25日 前言 通过前面几篇文章,我相信大家对于SharePoint Online的开发有了更加全面的认识,上一篇 介绍的SharePoint Add-in的开发, ...

  9. Spring Framework简介

    作者关于此主题早期文章 Spring框架快速入门 起源 要谈Spring的历史,就要先谈J2EE.J2EE应用程序的广泛实现是在1999年和2000年开始的,它的出现带来了诸如事务管理之类的核心中间层 ...

  10. [Learn AF3]第一章 如何使用App Framework 3.0 构造应用程序

    af3的变化非常大.参见[译]Intel App Framework 3.0的变化 一.应用需要引用的js脚本: af3中不在自己实现dom选择器,而是选择基于jquey或兼容jquery的库如zep ...

随机推荐

  1. manim边做边学--圆环面

    Torus类在制作数学.物理或工程领域的动画时具有广泛的应用场景. 比如,通过动态演示环面的拓扑变换(如内外翻转.扭曲等),帮助我们直观地理解拓扑不变量和同胚等概念: 此外,也可以模拟磁场线在环面导体 ...

  2. Blocked aria-hidden on an element because its descendant retained focus.

    背景 vue 2.6.10 报错:Blocked aria-hidden on an element because its descendant retained focus. The focus ...

  3. 方法区回收过程与GC的并发与并行

    主要回收废弃常量和无用的类 废弃常量包括字面量.类或接口.方法.字段的符号引用等 废弃指的是没有任何地方引用这个常量. 无用的类 满足的三个条件: 1.没有该类的任何实例存在 2.加载该类的Class ...

  4. 在线文档-Wiki平台

    GitBook 对于在线文档创作平台,当然还是首推GitBook GitBook为免费用户提供 10个空间(可以私有也可以公开) 支持自定义域名 gitbook本身是一个开源项目,你可以下载源代码自行 ...

  5. MySQL底层概述—4.InnoDB数据文件

    大纲 1.表空间文件结构 (1)表空间Tablesapce (2)段Segment (3)区Extend (4)页Page (5)行Row 2.Page结构 (1)页结构各部分说明 (2)页结构整体划 ...

  6. 整合Sleuth

    Sleuth是 springcloud 分布式跟踪解决方案. Sleuth 术语: 跨度(span ) :Sleuth 的基本工作单元,他用一个64位的id唯一标识.出ID外,span还包含 其他的数 ...

  7. Reviewbot 开源 | 这些写 Go 代码的小技巧,你都知道吗?

    Reviewbot 是七牛云开源的一个项目,旨在提供一个自托管的代码审查服务, 方便做 code review/静态检查, 以及自定义工程规范的落地. 自从上了 Reviewbot 之后,我发现有些 ...

  8. 谈谈Python中的接口与抽象基类

    接触Python比较早的朋友可能都有这样的体会,Python语言虽然也支持面向对象的编程方式, 但是,不像那些纯面向对象的语言(比如Java和.NET)那样严格和规范. 随着项目的规模逐步扩大之后,想 ...

  9. Docker跨主机跨服务器迁移

    ​主要作用: 就是让配置好的容器,可以得到复用,后面用到得的时候就不需要重新配置. 其中涉及到的命令有: docker commit 将容器保存为镜像 docker save -o 将镜像备份为tar ...

  10. Docker容器共享磁盘

    需求:.NET程序需要监控一个FTP上的文件变化并进行操作,在linux上使用原生目录时,不管怎么切换后台运行,总是会在一段时间运行后死掉. 方案:远程也不好debug,想了一下,干脆直接使用dock ...