0%

代理模式 - 结构型模式的操控者

在软件设计中,代理模式是一种结构型设计模式,它提供了一个代理对象来控制对其他对象的访问。代理模式可以用于多种场景,例如远程代理、虚拟代理、保护代理等。本文将深入讨论代理模式的概念、实现方式以及在实际应用中的使用场景。

代理模式的概念

代理模式(Proxy Pattern)是一种结构型设计模式,其核心思想是通过一个代理对象控制对其他对象的访问。代理对象充当了被代理对象的替代者,可以在访问时添加一些额外的逻辑,例如权限验证、懒加载等。

代理模式的 UML 类图

classDiagram
    class Subject {
        + Request(): void
    }

    class RealSubject {
        + Request(): void
    }

    class Proxy {
        - realSubject: RealSubject
        + Request(): void
    }

    Subject <|.. RealSubject
    Subject <|.. Proxy

代理模式的实现方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System;

// 抽象主题类
public abstract class Subject
{
public abstract void Request();
}

// 真实主题类
public class RealSubject : Subject
{
public override void Request()
{
Console.WriteLine("Real Subject Request");
}
}

// 代理类
public class Proxy : Subject
{
private RealSubject realSubject;

public override void Request()
{
// 在访问真实主题前可以添加一些额外的逻辑
if (realSubject == null)
{
realSubject = new RealSubject();
}

realSubject.Request();

// 在访问真实主题后可以添加一些额外的逻辑
}
}

代理模式的应用场景

代理模式适用于以下情况:

  1. 远程代理: 代理对象可以控制对远程对象的访问,例如通过网络访问远程服务器的对象。
  2. 虚拟代理: 代理对象可以在访问时延迟加载真实对象,提高系统性能。
  3. 保护代理: 代理对象可以控制对真实对象的访问权限,增加了安全性。
  4. 缓存代理: 代理对象可以缓存对真实对象的操作结果,提高系统的响应速度。

代理模式的优势

  1. 控制访问: 代理模式可以控制对真实对象的访问,可以在访问时添加一些额外的逻辑。
  2. 提高性能: 虚拟代理可以延迟加载真实对象,提高了系统的性能。
  3. 增加安全性: 保护代理可以控制对真实对象的访问权限,增加了系统的安全性。
  4. 实现懒加载: 代理模式可以实现懒加载,只有在真正需要时才加载真实对象。

使用示例

1
2
3
4
5
6
7
8
9
10
11
class Program
{
static void Main()
{
// 创建代理对象
Proxy proxy = new Proxy();

// 调用代理对象的操作方法,实际上会调用真实主题对象的操作方法
proxy.Request();
}
}

总结

代理模式是一种结构型设计模式,通过代理对象控制对其他对象的访问。代理模式在多种场景中有广泛的应用,例如远程代理、虚拟代理、保护代理等。在实际应用中,代理模式需要根据具体场景权衡性能、安全性和代码的清晰度。

原型模式 - 创建型模式的对象复制大师

在软件设计中,原型模式是一种创建型设计模式,它通过复制现有对象来创建新对象,从而避免了创建对象时的耗时操作。本文将深入探讨原型模式的概念、实现方式以及在实际应用中的使用场景。

原型模式的概念

原型模式(Prototype Pattern)是一种创建型设计模式,其核心思想是通过复制(克隆)现有对象来创建新对象。这种方式避免了从头创建对象的过程,提高了对象创建的效率。

原型模式的 UML 类图

classDiagram
    class Prototype {
        + Clone(): Prototype
    }

    class ConcretePrototype : Prototype {
        + Clone(): Prototype
        - state: string
    }

原型模式的实现方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;

// 原型接口
public interface Prototype
{
Prototype Clone();
}

// 具体原型类
public class ConcretePrototype : Prototype
{
private string state;

public ConcretePrototype(string state)
{
this.state = state;
}

public Prototype Clone()
{
return new ConcretePrototype(this.state);
}

public void ShowState()
{
Console.WriteLine($"State: {state}");
}
}

原型模式的应用场景

原型模式适用于以下情况:

  1. 对象的创建成本较大,但需要频繁地创建相似对象。
  2. 系统要求一个对象在多个场景中使用,但每个场景的状态略有差异。
  3. 需要保护对象的客户端免受对象变化的影响,同时希望能够动态地配置对象。

原型模式的优势

  1. 节省资源: 避免了重复创建相似对象的开销,提高了系统性能和资源利用率。

  2. 动态配置对象: 客户端可以动态地配置克隆对象的状态,实现动态变化。

  3. 简化对象创建: 将对象创建的过程封装在原型中,使得客户端无需关心对象的具体创建细节。

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Program
{
static void Main()
{
// 创建原型对象
ConcretePrototype prototype = new ConcretePrototype("Initial State");
prototype.ShowState();

// 克隆原型对象
ConcretePrototype clonedPrototype = (ConcretePrototype)prototype.Clone();
clonedPrototype.ShowState();

// 修改克隆对象的状态
clonedPrototype = (ConcretePrototype)prototype.Clone();
clonedPrototype.ShowState();
clonedPrototype = (ConcretePrototype)prototype.Clone();
clonedPrototype.ShowState();
}
}

总结

用原型实例指定创建对象的种类,并且通过拷贝(克隆)这些原型创建新的对象。克隆过程可“繁”可“简”,而且我们往往希望对于克隆过程实施更深入的控制,为了简化开发,我们还要准备点工具类完成不同的克隆过程。

原型模式是一种简单而有效的创建型设计模式,通过复制现有对象来创建新对象,提高了对象创建的效率。在某些场景下,特别是当对象创建成本较大且对象之间的差异较小时,原型模式能够带来显著的性能提升。在实际应用中,使用原型模式需要注意克隆对象的深拷贝和浅拷贝问题。

工厂模式与工厂方法模式 - 创建型模式的巧妙设计

在软件设计中,工厂模式和工厂方法模式是两种创建型设计模式,它们都旨在解决对象的创建问题。本文将深入讨论工厂模式和工厂方法模式的概念、应用场景以及实际代码示例。

工厂模式

工厂模式是一种创建型设计模式,它提供了一个通用的接口来创建对象,但具体的实例化过程由子类决定。这样的设计允许一个类在运行时确定实例化哪个具体类,而不是在编译时进行硬编码。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class 简单工厂模式
{
[Fact]
public void Test()
{
Operation oper;
oper = OperationFactory.CreateOperation("+");
oper.numberA = 1;
oper.numberB = 2;
double result = oper.GetResult();
}

public class OperationFactory
{
public static Operation CreateOperation(string operat)
{
Operation oper = null;
switch (operat)
{
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
}
return oper;
}
}

public class Operation
{
public double numberA { get; set; }
public double numberB { get; set; }
public virtual double GetResult()
{
double result = 0;
return result;
}
}
private class OperationAdd : Operation
{
public override double GetResult()
{
double result = numberA + numberB;
return result;
}
}
private class OperationSub : Operation
{
public override double GetResult()
{
double result = numberA - numberB;
return result;
}
}
}

工厂方法模式

工厂方法模式是工厂模式的一种变体,它通过将创建产品的方法延迟到子类来实现。每个具体工厂类都负责创建一种具体产品,从而使得系统更具可扩展性。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/// <summary>
/// 定义一个用于创建对象的接口,让子类决定实例化哪一个子类。工厂方法使一个类的实例化延迟到其子类
/// </summary>
public class 工厂方法模式
{
[Fact]
public void Test()
{
IFactory factory = new AddFactory();
Operation oper = factory.CreateOperation();
oper.numberA = 1;
oper.numberB = 2;
double result = oper.GetResult();
}
class Operation
{
public double numberA { get; set; }
public double numberB { get; set; }
public virtual double GetResult()
{
double result = 0;
return result;
}
}
class OperationAdd : Operation
{
public override double GetResult()
{
double result = numberA + numberB;
return result;
}
}
interface IFactory
{
Operation CreateOperation();
}
class AddFactory : IFactory
{
public Operation CreateOperation()
{
return new OperationAdd();
}
}
}

工厂模式和工厂方法模式的应用场景

  • 工厂模式适用场景: 当一个类负责创建的对象的类不确定,而需要根据具体情况进行选择时,可以使用工厂模式。例如,需要根据配置文件动态选择数据库连接。

  • 工厂方法模式适用场景: 当一个类不知道

它所需要的对象的类,但知道需要某个类来创建对象时,可以使用工厂方法模式。例如,需要在运行时决定创建哪个日志记录器。

工厂方法的意图非常明确,它把类的实例化过程延迟到子类,将new()的工作交给工厂完成。同时,增加一个抽象的工厂定义,解决一系列具有统一通用工厂方法的实体工厂问题。在.NET 平台中,我们可以借助配置、泛型和委托的方法在实现经典模式目的的同时,获得工厂类型与客户程序间更加松散的构造过程。

总结

工厂模式和工厂方法模式都是创建型设计模式,它们通过将对象的创建过程封装在工厂中,提高了代码的灵活性和可维护性。选择使用哪种模式取决于具体的需求和设计情景。这两种模式在实际开发中被广泛应用,能够有效地组织和管理对象的创建过程。

深入理解单例模式 - 创建型模式的精髓

单例模式是一种创建型设计模式,其目的是确保一个类只有一个实例,并提供全局访问点。在许多场景中,单例模式被用于管理全局状态、资源共享以及限制对象的创建。在本文中,我们将深入探讨单例模式的概念、实现方式以及在实际应用中的使用场景。

单例模式的概念

单例模式是设计模式中最简单但也是最常用的模式之一。其核心思想是通过限制一个类只能有一个实例,确保该实例能够被全局访问。这通常通过以下几个要素来实现:

  1. 私有构造函数: 防止外部通过构造函数创建实例。
  2. 私有静态变量: 用于保存实例。
  3. 公有静态方法(全局访问点): 用于获取实例。

单例模式的实现方式

在C#中,实现单例模式的方式有多种,以下是其中两种常见的实现方式:

1. 懒汉式单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/// <summary>
/// 懒汉式单例类
/// </summary>
class Singleton
{
private static Singleton instance;
private static readonly object syncRoot = new object();
public static Singleton GetInstance()
{
//双重锁定
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}

这种实现方式在需要时才创建实例,称为懒汉式。通过 lock 语句确保多线程环境下的安全创建。

2. 饿汉式单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/// <summary>
/// 懒汉式单例类
/// </summary>
class Singleton
{
private static Singleton instance;
private static readonly object syncRoot = new object();
public static Singleton GetInstance()
{
//双重锁定
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}

这种实现方式在类加载时就创建实例,称为饿汉式。由于在类加载时就创建,因此不存在多线程安全问题。

单例模式的应用场景

单例模式适用于以下场景:

  1. 资源共享: 当应用中需要共享资源(如配置信息、日志对象)时,单例模式能够确保只有一个实例处理这些共享资源。

  2. 全局状态管理: 当某个对象需要在系统中保存全局状态时,单例模式能够提供一个统一的入口点来管理这个状态。

  3. 唯一访问点: 当某个类的实例只能有一个访问点时,如工厂类、线程池等,单例模式能够确保只有一个实例提供访问点。

单例模式的注意事项

  1. 多线程安全: 在多线程环境下,懒汉式单例模式需要考虑线程安全问题,可通过 lockdouble-check 等方式解决。

  2. 延迟加载: 懒汉式单例模式支持延迟加载,但在需要时创建实例,可能会引入性能开销。

  3. 反序列化安全: 如果单例类可能被序列化和反序列化,需要实现 ISerializable 接口并提供 OnDeserialized 方法,以确保反序列化后仍然是单例。

总结

使用Singleton 模式的意图就是要保证一个类只有一个实例,同时提供客户程序一个访问它的全局访问点。虽然经典Singleton 模式旨在控制实例的数量,但受到种种“隐性”破坏因素的威胁,我们还需要实施各种针对性的实例数量控制手段。

单例模式是一种简单而强大的设计模式,适用于多种场景。通过合理选择懒汉式或饿汉式的实现方式,可以满足不同的需求。在实际应用中,合理使用单例模式能够提高代码的可维护性和整体设计的灵活性。

创建者模式 - 创建型模式的优雅构建者

在软件设计中,创建者模式是一种创建型设计模式,旨在通过将一个复杂对象的构建过程与其表示分离,从而使同样的构建过程可以创建不同的表示。本文将深入讨论创建者模式的概念、实现方式以及在实际应用中的使用场景。

创建者模式的概念

创建者模式(Builder Pattern)是一种对象创建型设计模式,它提供了一种分步构建复杂对象的方法,使得同样的构建过程可以创建不同的表示。通过将一个大的构建过程分解为多个小的构建步骤,可以更灵活地创建对象。

创建者模式的实现方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
using System;
using System.Collections.Generic;

// 产品类
public class Product
{
private List<string> parts = new List<string>();

public void AddPart(string part)
{
parts.Add(part);
}

public void Show()
{
Console.WriteLine("Product Parts:");
foreach (var part in parts)
{
Console.WriteLine(part);
}
}
}

// 抽象构建者接口
public interface IBuilder
{
void BuildPartA();
void BuildPartB();
Product GetResult();
}

// 具体构建者
public class ConcreteBuilder : IBuilder
{
private Product product = new Product();

public void BuildPartA()
{
product.AddPart("Part A");
}

public void BuildPartB()
{
product.AddPart("Part B");
}

public Product GetResult()
{
return product;
}
}

// 指导者
public class Director
{
private IBuilder builder;

public Director(IBuilder builder)
{
this.builder = builder;
}

public void Construct()
{
builder.BuildPartA();
builder.BuildPartB();
}
}

创建者模式的应用场景

创建者模式适用于以下情况:

  1. 当一个对象有复杂的内部结构(多个部分)时。
  2. 当构建过程必须独立于创建具体对象的表示时。
  3. 当同样的构建过程需要创建不同的表示时。

创建者模式的优势

  1. 分步构建: 将构建过程分解为多个步骤,使得对象的构建更加灵活,可以根据需要选择性地执行构建步骤。

  2. 独立构建过程和表示: 构建者模式将构建过程和表示分离,使得同样的构建过程可以创建不同的表示,客户端无需关心对象的具体构建过程。

  3. 更好的封装性: 客户端只需要知道 Director 和 IBuilder 接口,无需关心具体的构建者和产品实现,从而更好地封装了对象的创建过程。

总结

创建者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。根据上下文需要,我们除了要设计具有装配能力的创建者,必要的时候还要能够有序拆解目标实例。

创建者模式是一种非常有用的创建型设计模式,它通过将复杂对象的构建过程分解为多个小的构建步骤,提供了一种优雅的构建对象的方式。在实际应用中,当对象具有复杂的内部结构、需要独立构建过程和表示、或者构建过程需要灵活性时,创建者模式是一个很好的选择。

深入探讨抽象工厂模式 - 创建型模式的灵活工厂设计

在软件设计中,抽象工厂模式是一种创建型设计模式,旨在提供一个接口用于创建相关或依赖对象的家族,而不需要明确指定它们的具体类。本文将深入探讨抽象工厂模式的概念、实现方式以及在实际应用中的使用场景。

抽象工厂模式的概念

抽象工厂模式是一种创建型设计模式,它提供一个接口,用于创建一系列相关或依赖对象的家族,而无需指定它们的具体类。抽象工厂允许客户端代码使用抽象接口来创建一组相关的产品,而不必关心这些产品的具体实现。

抽象工厂模式的实现方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/// <summary>
/// 提供一个创建一系列相关或依赖对象的的接口
/// 而无需指定它们具体的类
/// </summary>
public class 抽象工厂模式
{
[Fact]
public void Test()
{
User user = new User();

IFactory factory = new SqlserverFactory();
IUser iu = factory.CreateUser();

iu.Insert(user);
iu.GetUser(1);
}
/// <summary>
/// 定义一个创建访问User表对象的抽象的工厂接口
/// </summary>
interface IFactory
{
IUser CreateUser();
}
/// <summary>
/// 实例化SqlserverUser
/// </summary>
class SqlserverFactory : IFactory
{
public IUser CreateUser()
{
return new SqlserverUser();
}
}
/// <summary>
/// 实例化AccessUser
/// </summary>
class AccessFactory : IFactory
{
public IUser CreateUser()
{
return new AccessUser();
}
}
/// <summary>
/// 用户客户端访问,解除与具体数据库访问的耦合
/// </summary>
interface IUser
{
void Insert(User user);
User GetUser(int id);
}
/// <summary>
/// sqlserver具体类
/// </summary>
class SqlserverUser : IUser
{
public void Insert(User user)
{
Console.WriteLine("sqlserver 新增一条数据");
}

public User GetUser(int id)
{
Console.WriteLine("sqlserver 获取一条数据");
return null;
}
}
/// <summary>
/// Access具体类
/// </summary>
class AccessUser : IUser
{
public User GetUser(int id)
{
Console.WriteLine("Access 获取一条数据");
return null;
}

public void Insert(User user)
{
Console.WriteLine("Access 新增一条数据");
}
}

class User
{
public int Id { get; set; }
public string Name { get; set; }
}
}

抽象工厂模式的应用场景

抽象工厂模式适用于以下情况:

  1. 系统需要独立于它的产品的创建、组合和表示时。
  2. 系统要配置多个产品族中的一个,以适应特定的上下文需求。
  3. 强调一系列相关的产品对象的设计以便进行联合使用时。
  4. 提供一个产品类库,而只想显示它的接口而不是实现时。

总结

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类型。借助类型映射器、配置、委托等手段都可以进一步扩展抽象工厂构造“一组相关或相互依赖对象接口”的能力。

抽象工厂模式是一种强大的设计模式,它提供了一种创建相关或依赖对象家族的方式,使得系统更具灵活性和可扩展性。通过使用抽象工厂模式,可以隐藏具体产品的实现细节,使得客户端代码更加独立于具体产品的变化。在设计中,选择合适的设计模式取决于问题的复杂性和需求的变化性,抽象工厂模式是一个很好的选择。

设计模式的来源:

设计模式是前人的开发总结,可以解决复杂的代码架构问题,可以使用各种开发套路解决开发过程中出现的各种问题。灵活的使用设计模式可以提高代码的质量,让代码的复用性、可维护性、可读性、稳健性以及安全性得到很高提升的解决方案

设计模式从1905年就已经被GOF(四人组)提出,并且记录到了《设计模式:可复用面向对象软件的基础》这本书里面。书中共记录了23种设计模式,这对于设计模式的发展有里程碑的意义,这23种设计模式也被为称为《GOF设计模式》

随着很多年的发展,网络上面的设计模式资料没有发生很大的变化,还是这23种模式,但是大多的资料是java语言版本的,但是在c#语言方面,为了方便开发者使用设计模式,在dotnet框架的设计方案中已经在平台层面添加了很多的设计模式内容。
我们后面围绕这设计模式的场景和具体方案,来具体了解一下设计模式的魅力吧。

设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。这些模式解决了特定问题,让开发人员能够更有效地进行软件开发。设计模式通常可以分为三大类:

1. 创建型模式(Creational Patterns):

这些模式关注对象的创建机制,试图以适合的方式创建对象。它们主要包括:

  • 工厂方法模式(Factory Method Pattern): 定义一个用于创建对象的接口,让子类决定实例化哪个类。

  • 抽象工厂模式(Abstract Factory Pattern): 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

  • 建造者模式(Builder Pattern): 将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

  • 原型模式(Prototype Pattern): 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

  • 单例模式(Singleton Pattern): 保证一个类只有一个实例,并提供一个全局访问点。

2. 结构型模式(Structural Patterns):

这些模式关注类和对象的组合,用于形成更大的结构。它们主要包括:

  • 适配器模式(Adapter Pattern): 将一个类的接口转换成客户希望的另外一个接口。

  • 桥接模式(Bridge Pattern): 将抽象部分与实现部分分离,使它们可以独立变化。

  • 组合模式(Composite Pattern): 将对象组合成树形结构以表示”部分-整体”的层次结构。

  • 装饰者模式(Decorator Pattern): 动态地给对象添加一些额外的职责。

  • 外观模式(Facade Pattern): 为子系统中的一组接口提供一个一致的界面。

  • 享元模式(Flyweight Pattern): 通过共享技术来有效地支持大量细粒度的对象。

  • 代理模式(Proxy Pattern): 为其他对象提供一种代理以控制对这个对象的访问。

3. 行为型模式(Behavioral Patterns):

这些模式关注对象之间的通信,以及算法的责任分配。它们主要包括:

  • 责任链模式(Chain of Responsibility Pattern): 使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合。

  • 命令模式(Command Pattern): 将一个请求封装成一个对象,从而使用户可以用不同的请求对客户进行参数化。

  • 解释器模式(Interpreter Pattern): 定义语言的文法,并且建立一个解释器来解释该语言中的句子。

  • 迭代器模式(Iterator Pattern): 提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露其内部的表示。

  • 中介者模式(Mediator Pattern): 用一个中介对象来封装一系列的对象交互。

  • 备忘录模式(Memento Pattern): 在不破坏封装性的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。

  • 观察者模式(Observer Pattern): 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

  • 状态模式(State Pattern): 允许一个对象在其内部状态改变时改变它的行为。

  • 策略模式(Strategy Pattern): 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。

  • 模板方法模式(Template Method Pattern): 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。

  • 访问者模式(Visitor Pattern): 表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

这些设计模式在不同的情境下解决了软件开发中的各种问题,开发人员可以根据实际需求选择合适的设计模式来提高代码的可维护性、可扩展性和重用性。

1.0 2002 年 1 月 Visual Studio .NET 2002

目标是一个简单、现代、通用的面向对象语言,c#刚推出的时候,还没有现在常用的泛型、linq,c#早期和java代码格式非常像,在windows平台上,c#1.0是java的一个可行的替代之选

C# 1.0 的主要功能包括:

  • 结构
  • 接口
  • 事件
  • 属性
  • 委托
  • 运算符和表达式
  • 语句
  • 特性

1.2 2003 年 4 月 Visual Studio .NET 2003

添加了一个小改动 在foreach循环的时候会对  IEnumerator  的 IDisposable实现调用 Dispose

2.0 2005年11月 Visual Studio 2005

新加的功能:

  • 泛型
  • 分部类型
  • 匿名方法
  • 可以为 null 的值类型
  • 迭代器
  • 协变和逆变
    还有其它的更新:
  • getter/setter 单独可访问性
  • 方法组转换(委托)
  • 静态类
  • 委托推断

重点说明:

泛型:在c#2.0 开始支持了 泛型 (通过泛型,类型和方法可以操作任意类型,同时保持类型的安全性。如 List,获得List、List并且可以对这些字符串或整数执行类型安全操作,现时进行循环访问。在泛型出现之前,想达到相同的效果 需要派生自 ArrayList、ListInt类型,还需要进行操作Object强制转换,明显使用泛型更方便高效)
迭代器:迭代器允许使用foreach检查 可枚举类 如List的所有项。 迭代器可以提升语言的可读性
此时java已经发布了包含了泛型和迭代器的版本,c#在追赶java
元组返回内容在DOTNET异常处理的优化
将错误异常对象返回到元组参数,判断异常对象是否为null,
tps可以从900提升到3k

3.0 2007年 11月  Visual Studio 2008

新增的功能:

  • 自动实现的属性
  • 匿名类型
  • 查询表达式
  • Lambda 表达式
  • 表达式树
  • 扩展方法
  • 隐式类型本地变量
  • 分部方法
  • 对象和集合初始值设定项

重点说明:
构造linq的时候可以通过 表达式数、Lambda表达式、匿名类型 实现。这些概念让c#不只是一种面向对象的语言,也可以进行函数式变成,成为了一种混合语言。如计算总合不需要使用for求和,可以通过List.Sum()方法。查询表达式和扩展方法让编程更方便了。

4.0 2010年4月 Visual Studio 2010

新增的功能;

  • 动态绑定
  • 命名参数/可选参数
  • 泛型协变和逆变
  • 嵌入的互操作类型
    重点说明:
    dynamic关键字可以创建和动态类型语言(如js)类似的构造,c#提供了强大的动态类型的语言功能。(个人不建议在dotnet大范围使用dynamic,会有类型相关出错的可能性)
    泛型协变和遡变在框架和库的开发者使用的较多。

5.0 2012年8月  Visual Studio 2012

新增的功能:

  • 异步成员
  • 调用方信息特性
  • 代码工程:C# 5.0 中的调用方信息属性

重点说明:
async await 是 这个版本的主角,在语言层面引入异步操作的关键字,异步代码非常简单实现
调用方信息特性让你可以轻松检索上下文的信息,不需要采用大量样本反射代码。 这在诊断和日志记录任务中也很有用。
6.0 2015年 7月 Visual Studio 2015
新增的功能

  • 静态导入
  • 异常筛选器
  • 自动属性初始化表达式
  • Expression bodied 成员
  • Null 传播器
  • 字符串内插
  • nameof 运算符
    其他新功能包括:
  • 索引初始化表达式
  • Catch/Finally 块中的 Await
  • 仅限 getter 属性的默认值

    重点说明:

语言层面没有太大的功能添加,但是 c#编译器使用c#编写了。Roslyn 重要的特性就是Compiler as a Service 简单的讲,就是就是将编译器开放为一种可在代码中调用的服务,

7.0 2017年3月 Visual Studio 2017

新增功能:

  • out 变量
  • 元组和析构函数
  • 模式匹配
  • 本地函数
  • 已扩展 expression bodied 成员
  • ref 局部变量
  • 引用返回

其他功能包括:

  • 弃元
  • 二进制文本和数字分隔符
  • 引发表达式

重点说明:
重点是使代码变得更简洁,此时的dotnet在dotnetcore 的云平台和可移植性发力。
7.1 2017年8月 Visual Studio 2017

此版本中新增的语言功能包括:

  • asyncMain 方法
  • 应用程序的入口点可以含有 async 修饰符
  • default 文本表达式
  • 在可以推断目标类型的情况下,可在默认值表达式中使用默认文本表达式。 让代码简洁优雅
  • 推断元组元素名称
  • 在许多情况下,可通过元组初始化来推断元组元素的名称。
  • 泛型类型参数的模式匹配
  • 可以对类型为泛型类型参数的变量使用模式匹配表达式。
    编译器有 -refout 和 -refonly 两个选项,可用于控制引用程序集生成

7.2 2017年11月 Visual Studio 2017

C# 7.2 版添加了几个小型语言功能:

  • stackalloc 
  • 对支持模式的任何类型使用 fixed 
  • 无需固定即可访问固定的字段。
  • 重新分配 ref 
  • 声明 readonly struct  in 
  • 在实参上添加 in 
  • 对方法返回项使用  ref readonly 
  • 声明  ref struct 
  • 使用其他泛型约束。
  • 非尾随命名参数
  • 命名的参数可后接位置参数。
  • 数值文字中的前导下划线
  • 数值文字现可在任何打印数字前放置前导下划线。
  • private protected 访问修饰符
  • private protected 
  • 条件 ref
  • 现在可以引用条件表达式 ?:的结果

7.3 2018年5月

C# 7.3 版本有两个主要主题。 第一个主题提供使安全代码的性能与不安全代码的性能一样好的功能。 第二个主题提供对现有功能的增量改进。 此外,此版本中还添加了新的编译器选项。

8.0 2019年9月

C# 8.0 版是专门面向 .NET C# Core 的第一个主要 C# 版本。 一些功能依赖于新的 CLR 功能,而其他功能依赖于仅在 .NET Core 中添加的库类型。 

C# 8.0 向 C# 语言添加了以下功能和增强功能:

  • Readonly 成员
  • 默认接口方法
  • 模式匹配增强功能
  • switch 表达式
  • 属性模式
  • 元组模式
  • 位置模式
  • Using 声明
  • 静态本地函数
  • 可处置的 ref 结构
  • 可为空引用类型
  • 异步流
  • 索引和范围
  • Null 合并赋值
  • 非托管构造类型
  • 嵌套表达式中的 Stackalloc
  • 内插逐字字符串的增强功能

9.0 2020年11月

C# 9 随 .NET 5 一起发布。 它是面向 .NET 5 版本的任何程序集的默认语言版本。 它包含以下新功能和增强功能:

  • 记录
  • 仅限 Init 的资源库
  • 顶级语句
  • 模式匹配增强功能
  • 性能和互操作性
  • 本机大小的整数
  • 函数指针
  • 禁止发出 localsinit 标志
  • 调整和完成功能
  • 目标类型的 new 表达式
  • static 匿名函数
  • 目标类型的条件表达式
  • 协变返回类型
  • 扩展 GetEnumerator 支持 foreach 循环
  • Lambda 弃元参数
  • 本地函数的属性
  • 支持代码生成器
  • 模块初始值设定项
  • 分部方法的新功能

主要内容:

  1. 删除不必要的模式:顶级语句意味着主程序将更易于读取。 减少了不必要的模式:命名空间、Program 类和 static void Main() 都是不必要的。
  2. 将数据与算法分离:records 的引入为遵循值语义的引用类型提供了简洁的语法,以实现相等性。 你将使用这些类型来定义通常定义最小行为的数据容器。 仅限 Init 的资源库在记录中提供了非破坏性修改功能(with 表达式)。 C# 9 还添加了协变返回类型,以便派生记录可以重写虚拟方法,并返回从基方法的返回类型派生的类型。
  3. 更多位置提供更多模式:模式匹配功能以多种方式进行了扩展。 数值类型现在支持范围模式。 可以使用and、or 和not 模式组合模式。 可以通过添加括号来阐明更复杂的模式。
  4. 高性能计算相关(不安全的代码,个人不建议使用):
  • nint 和 nuint 类型对目标cpu的本机大小整数类型进行建模 
  • 函数指针 提供类似委托功能,同时避免创建委托对象所需的分配
  • localsinit  指令可以省略以保存指令

另一组改进支持代码生成器添加功能的场景

  • 模块初始化表达式 是程序集加载时运行时调用的方法
  • 分部方法 支持新的可访问修饰符和非 void 返回类型。 在这些情况下,必须提供一个实现。

小功能,提高了开发人员的工作效率,包括编写和读取代码:

  • 目标类型  new 表达式
  • static 匿名函数
  • 目标类型的条件表达式
  • 扩展 GetEnumerator()  支持 foreach 循环 
  • Lambda 表达式可以声明弃元参数
  • 特性可应用于本地函数

C# 9 版本继续致力于让 C# 成为一种新式通用编程语言。 功能继续支持新式工作负载和应用程序类型。

10 2021年11月

C# 10 继续致力于删除不必要的模式、将数据与算法分离以及提高 .NET 运行时的性能等主题。

C# 10 向 C# 语言添加了以下功能和增强功能:

  • 记录结构
  • 结构类型的改进
  • 内插字符串处理程序
  • global using 指令
  • 文件范围的命名空间声明
  • 扩展属性模式
  • 对 Lambda 表达式的改进
  • 可使用 const 内插字符串
  • 记录类型可密封 ToString()
  • 改进型明确赋值
  • 在同一析构中可同时进行赋值和声明
  • 可在方法上使用 AsyncMethodBuilder 属性
  • CallerArgumentExpression 属性
  • 增强的 #line pragma

11 2023年11月

  1. C# 11 引入了泛型数学以及支持该目标的几个功能。 可以为所有数字类型编写一次数值算法。
  2. 简化 struct 类型处理,例如所需成员和自动默认结构
  3. 使用原始字符串文本、字符串内插中的换行符和 UTF-8 字符串文本可以更轻松地处理字符串。
  4. 文件本地类型等功能使源生成器更简单。
  5. 最后,列表模式添加了对模式匹配的更多支持。

C# 11 中增加了以下功能:

  • 原始字符串字面量
  • 泛型数学支持
  • 泛型属性
  • UTF-8 字符串字面量
  • 字符串内插表达式中的换行符
  • 列表模式
  • 文件本地类型
  • 必需的成员
  • 自动默认结构
  • 常量 string 上的模式匹配 Span
  • 扩展的 nameof 范围
  • 数值 IntPtr
  • ref 字段和 scoped ref
  • 改进了方法组向委托的转换
  • 警告波 7

内容参考:

https://learn.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-version-history

为简单起见,通常建议使用 wsl --install 安装适用于 Linux 的 Windows 子系统,但如果运行的是旧版 Windows,则可能不支持这种方式。 下面介绍了手动安装步骤。

阅读全文 »