C#语言发展历程(1-7)

一、类型发展

C#1中是没有泛型的 在C#2中在逐渐推出泛型。C#2还引入了可空类型。

示例:C#泛型(详解)-CSDN博客

1 C#3:引入了匿名类型、和隐式的局部变量(var)

匿名类型:我们主要是使用在LINQ查询语句。就算没有LINQ查询语句我们在一种类型只在一个方法中,我们创建数据类型供单一方法的使用,的这种方式也不可取。不过需要注意匿名类型的作用域只在声明的局部作用域中能使用。

示例:高级C#技术(二)-CSDN博客

2 C#7中可以采用Readonly Struct 自定义结构

举个例子:

cs 复制代码
public readonly struct Point
{
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}
cs 复制代码
Point p1 = new Point(2, 3);
Console.WriteLine($"p1: ({p1.X}, {p1.Y})");

// 尝试修改结构的属性值,将会引发编译错误
// p1.X = 5;
// p1.Y = 10;

Point p2 = new Point(5, 10);
Console.WriteLine($"p2: ({p2.X}, {p2.Y})");

// 结构的属性值无法修改,因此下面的赋值操作是创建了一个新的Point实例
Point p3 = p2;
Console.WriteLine($"p3: ({p3.X}, {p3.Y})");

示例解释:

上述代码中,我们创建了一个Point对象,打印了它的坐标,并尝试修改它的属性值。由于Point是不可变的结构,所以修改属性值的操作会导致编译错误。然后,我们创建了另一个Point对象p2,并将其赋值给p3。由于结构是不可变的,所以赋值操作实际上是创建了一个新的Point实例。

3 C#7中引入了元组:

元组可以替代我们前面提到的匿名类型。其中不同的是元组可以用于方法的返回类型,和参数。建议放在内部的API中不对外暴露。因为元组只是对简单的值组合进行一个赋值。并没有对其封装。

举个例子:

你可以使用如下的语法来创建一个元组:

cs 复制代码
var myTuple = (value1, value2, value3);

你还可以给元组的成员命名,以增加代码的清晰度:

cs 复制代码
var myNamedTuple = (Name: "John", Age: 30, City: "New York");

也可创建匿名类型 任何类型都可以创建

怎么使用?

cs 复制代码
 var myTuple = (45, 88, 99);
 Console.WriteLine(myTuple.Item1);//代表第一个元素   结果 45

如果您给元组的成员命名了 那么就可以使用名称来输出

cs 复制代码
 var myNamedTuple = (Name: "John", Age: new { maximum = "100", minimum = "10" }, City: "New York");
 Console.WriteLine(myNamedTuple.Name);

当需要访问元组的成员时,你可以使用点符号或者解构语法来拆包:

cs 复制代码
var myNamedTuple = (Name: "John", Age: new { maximum = "100", minimum = "10" }, City: "New York");
Console.WriteLine(myNamedTuple.Name);
var (name, age, city) = myNamedTuple;
Console.WriteLine(name);
Console.WriteLine(age.maximum);  // 访问嵌套匿名类型的属性
Console.WriteLine(city);

下面是一个示例,展示了如何在方法的返回类型和参数中使用元组:

cs 复制代码
public static (int, string) GetPerson()
{
    int age = 25;
    string name = "John Doe";
    return (age, name);
}

public static void PrintPerson((int, string) person)
{
    Console.WriteLine("Name: " + person.Item2);
    Console.WriteLine("Age: " + person.Item1);
}

// 使用示例
var person = GetPerson();
PrintPerson(person);

C#8中引入了可空引用类型:C#8假设没有使用任何显示声明的返回值、参数、属性、全局或局部变量都是默认为为空类型的。

二、代码更简洁

1 C#1中,需要先写一个委托可以指向方法,然后再写一大段代码来创建委托。

举个例子:

cs 复制代码
class Myeven
{
    public delegate void MyAction(object sender, ElapsedEventArgs e);
    public event MyAction myeven;
    Timer Timer;
    public Myeven()
    {
        Timer ??= new Timer();
        Timer.Elapsed +=  new  ElapsedEventHandler(DLonti);
    }

    private void DLonti(object sender, ElapsedEventArgs e)
    {
       
    }
}

2 C#2引入方法组转换和匿名方法后就可以采用以下形式,匿名方法没有参数列表则可以忽略

cs 复制代码
class Myeven
{
    public delegate void MyAction(object sender, ElapsedEventArgs e);
    public event MyAction myeven;
    Timer Timer;
    public Myeven()
    {
        Timer ??= new Timer();
        Timer.Elapsed += delegate (object L, ElapsedEventArgs elapsedEventArgs)
        {
            //方法体
        };
    }
}

提示:在匿名方法当中您必须显示指定参数类型。

3 C#3推出Lambda表达式几乎具备了匿名函数的所有优点而且它的语法更简洁

cs 复制代码
class Myeven
{
    public delegate void MyAction(object sender, ElapsedEventArgs e);
    public event MyAction myeven;
    Timer Timer;
    public Myeven()
    {
        Timer ??= new Timer();
        Timer.Elapsed += (obj, e) => { //隐式声明参数列表
        
            //方法体
        };
        //Timer.Elapsed += (object obj, ElapsedEventArgs e) => {//显示声明参数列表

        //    //方法体
        //};
    }
}

4 C#3引入了对象初始化和集合初始化。

示例:高级C#技术(一)-CSDN博客

5 C#3推出了自动属性

举个例子:

cs 复制代码
class Myeven
{
	//自动属性 C#3中引人的
    public int MyProperty { get; set; }

	private int myVar;
    //传统属性
    public int MyProperty2
	{
		get { return myVar; }
		set { myVar = value; }
	}

}

6 C#6引入了表达式主体成员

在上面的示例中,我们可以将 MyProperty2 属性改写为使用表达式主体成员的形式,

如下所示:

cs 复制代码
public int MyProperty2
{
    get => myVar;
    set => myVar = value;
}

示例解释:

我们使用 => 箭头运算符来定义属性的读取和写入逻辑。对于 get 访问器,我们直接返回 myVar 字段的值;对于 set 访问器,我们将属性的值赋给 myVar 字段。

三、字符串处理

1 C#4引用了动态类型

示例:高级C#技术(二)-CSDN博客

2 C#5引入了调用方法信息特性

举个例子:

cs 复制代码
using System;
using System.Runtime.CompilerServices;

public class Program
{
    public static void Main(string[] args)
    {
        LogMessage("Hello, world!");
    }

    public static void LogMessage(string message,
        [CallerFilePath] string filePath = "",
        [CallerLineNumber] int lineNumber = 0,
        [CallerMemberName] string memberName = "")
    {
        Console.WriteLine($"Message: {message}");
        Console.WriteLine($"File Path: {filePath}");
        Console.WriteLine($"Line Number: {lineNumber}");
        Console.WriteLine($"Member Name: {memberName}");
    }
}

示例解释:

在上面的示例中,我们定义了一个名为 LogMessage 的方法,并将其标记为使用了 "调用方信息特性"。在 LogMessage 方法的参数中,我们使用了 CallerFilePathCallerLineNumberCallerMemberName 属性。这些属性会自动获取调用方的文件路径、行号和成员名称。

Main 方法中调用 LogMessage 方法时,会将参数传递给 LogMessage。当执行到 LogMessage 方法时,你将看到输出的结果如下:

输出结果:

3 C#6引入了nameof 运算符用于获取变量类型方法和成员的名字

举个例子:

cs 复制代码
class Myeven:INotifyPropertyChanged
{
	private int myVar;
	public int MyProperty
	{
		get { return myVar; }
		set { myVar = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(myVar))); }//nameof(myVar)替代原来的 "myVar"
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

4 C#6引入了内插字符串字面量

举个例子:

cs 复制代码
class Myeven
{
    private int name;
    public int Name
    {
        get { return name; }
        set { name = value; }
    }
    public Myeven()
    {
        Console.WriteLine("姓名"+Name);
        Console.WriteLine($"姓名{Name}");
    }
}

只是部分内容分享其实还有很多我没有提及到

相关推荐
Yaml444 分钟前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
小码编匠2 小时前
一款 C# 编写的神经网络计算图框架
后端·神经网络·c#
AskHarries2 小时前
Java字节码增强库ByteBuddy
java·后端
佳佳_2 小时前
Spring Boot 应用启动时打印配置类信息
spring boot·后端
许野平3 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
BiteCode_咬一口代码4 小时前
信息泄露!默认密码的危害,记一次网络安全研究
后端
Envyᥫᩣ5 小时前
C#语言:从入门到精通
开发语言·c#
齐 飞5 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
LunarCod5 小时前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发