内容来自书籍《C# 10 in a Nutshell》
Author:Joseph Albahari
需要该电子书的小伙伴,可以留下邮箱,有空看到就会发送的
c#是一门多用途,类型安全,面向对象的编程语言。
Unified type system,统一类型系统
c#的最基本组成部分是一个封装了数据的集合和函数,这叫做一个类型。c#有一个统一的类型系统,所有类型的最终继承自一个公共的类型,这意味着无论是业务对象还是基本类型都共享相同的基本功能,比如说,它们都有ToString
方法
Classes and interfaces,类和接口
在传统的面向对象范式中,只有唯一一种类型就是类。在c#中,有几种类型,一种是接口。接口就像一个不能携带数据的类,所以接口只有动作的定义,它可以多继承
Properties, methods, and events
在纯面向对象中,所有的函数都是方法。在c#,方法只是函数的其中一种,属性和事件也算是函数。属性是封装了对象一部分状态的函数。事件是简化了对象状态变化时引发的动作的函数
除了面向对象,c#也借鉴了函数式编程的概念
Functions can be treated as values
在c#中,函数也算是一等公民了,它可以被当作值来传递,这个涉及一个概念,叫做delegates
,它是函数的其中一种类型,可以被当作值传递到其他函数
supports patterns for purity
函数式编程的核心是避免使用可变变量,而使用声明式模式。C # 有一些关键特性可以帮助处理这些模式,包括能够动态编写匿名函数来“捕获”变量(lambda 表达式) ,以及能够通过查询表达式执行list或响应式编程。C # 还提供了record
,这使得编写不可变(只读)类型变得很容易。
支持c#运行的Runtimes由Common Language Runtime
(CLR)和Base Class Library
(BCL)组成。一个运行时也可以包括一个高层的application layer
提供给开发者。
CLR提供了必要的运行时服务,比如自动内存管理和错误处理。
C#被叫做托管的语言,因为它会被编译成一种叫做Intermediate Language(IL)
的托管代码。然后CLR
会将IL
翻译成目标机器的native code
。这涉及一个叫做Just-in-Time (JIT)
的编译器。还有一种叫做Ahead-of-time(AOT)
的编译器也可以使用,这种编译器会提高大型应用的启动速度。
托管代码的容器叫做assembly
程序集。它不仅仅包含IL,还有类型信息(metadata)。metadata的存在允许assemblies引用其他assemblies的类型而不需要额外的文件,程序当然也可以查找自己的metadata,这叫做reflection
反射,甚至可以在运行时生成新的IL托管代码
一个CLR总是关联着一个程序集的集合,叫做Base Class Library (BCL)
。BCL提供了一些核心功能给开发人员,比如集合、IO、文本处理、XML/JSON序列化、网络、加密、并发、并行编程。还有一些C#语言自身特有的特性,比如枚举器、查询和异步,还有反射和内存管理
一个runtime(也叫做框架)是一个下载并安装之后的可部署的单元。一般由一个CLR和它的BCL,还有可选的application layer
,这个是支持你编写一些特殊的应用,比如Web、mobile、rich client等,如果只是编写一些non-UI的应用,那么不需要application layer
.NET 6 是微软的开源运行时,可以编写Web和Console应用并运行在Windows、Linux和macOS;rich client可以运行在Windows7-11和macOS;moblie app运行在iOS和Android
.NET 6 没有预装在Windows上。启动会有信息提示安装哪个运行时,也可以通过构建self-contained
的部署程序来避免这种情况
.NET 6 的前任是.NET 5,.NET 5 的前任是.NET Core 3,微软将Core 去除和Versiong 4 跳过了。为了避免和.NET Framework 4.x
namespace MyNamespace; // 将这个命名空间扩大到整个文件 class Class1 {} // inside MyNamespace class Class2 {} // inside MyNamespace
global using System; global using System.Collection.Generic;
会将项目中的所有文件都导入这个命名空间
var a1 = new { A = 1, B = 2, C = 3, D = 4, E = 5 }; var a2 = a1 with { E = 10 }; Console.WriteLine (a2); // { A = 1, B = 2, C = 3, D = 4, E = 10 }
匿名创建一个类之后,可以使用with
来将特定的元素修改,其他元素照搬,来创建一个新的类
var point = (3, 4); double x = 0; (x, double y) = point;
解构元组,可以一个是引用已有的变量,一个是新变量
record struct Point (int X, int Y);
// 隐式推导 var greeter = () => "Hello, world"; // 隐式推导,入参需要写类型 var square = (int x) => x * x; // 可以指定返回类型 var sqr = int (int x) => x; M1 (() => "test"); // Implicitly typed to Func<string> M2 (() => "test"); // Implicitly typed to Func<string> M3 (() => "test"); // Implicitly typed to Expression<Func<string>> void M1 (object x) {} void M2 (Delegate x) {} void M3 (Expression x) {} // 可以添加attributes Action a = [Description("test")] () => { };
var obj = new Uri ("https://www.linqpad.net"); if (obj is Uri { Scheme.Length: 5 }) // 等价于 if (obj is Uri { Scheme: { Length: 5 }})