一、类型发展
C#1中是没有泛型的 在C#2中在逐渐推出泛型。C#2还引入了可空类型。
示例:C#泛型(详解)-CSDN博客
1 C#3:引入了匿名类型、和隐式的局部变量(var)
匿名类型:我们主要是使用在LINQ查询语句。就算没有LINQ查询语句我们在一种类型只在一个方法中,我们创建数据类型供单一方法的使用,的这种方式也不可取。不过需要注意匿名类型的作用域只在声明的局部作用域中能使用。
示例:高级C#技术(二)-CSDN博客
2 C#7中可以采用Readonly Struct 自定义结构
举个例子:
public readonly struct Point
{public int X { get; }public int Y { get; }public Point(int x, int y){X = x;Y = y;}
}
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中不对外暴露。因为元组只是对简单的值组合进行一个赋值。并没有对其封装。
举个例子:
你可以使用如下的语法来创建一个元组:
var myTuple = (value1, value2, value3);
你还可以给元组的成员命名,以增加代码的清晰度:
var myNamedTuple = (Name: "John", Age: 30, City: "New York");
也可创建匿名类型 任何类型都可以创建
怎么使用?
var myTuple = (45, 88, 99);Console.WriteLine(myTuple.Item1);//代表第一个元素 结果 45
如果您给元组的成员命名了 那么就可以使用名称来输出
var myNamedTuple = (Name: "John", Age: new { maximum = "100", minimum = "10" }, City: "New York");Console.WriteLine(myNamedTuple.Name);
当需要访问元组的成员时,你可以使用点符号或者解构语法来拆包:
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);
下面是一个示例,展示了如何在方法的返回类型和参数中使用元组:
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中,需要先写一个委托可以指向方法,然后再写一大段代码来创建委托。
举个例子:
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引入方法组转换和匿名方法后就可以采用以下形式,匿名方法没有参数列表则可以忽略
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表达式几乎具备了匿名函数的所有优点而且它的语法更简洁
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推出了自动属性
举个例子:
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
属性改写为使用表达式主体成员的形式,
如下所示:
public int MyProperty2
{get => myVar;set => myVar = value;
}
示例解释:
我们使用
=>
箭头运算符来定义属性的读取和写入逻辑。对于get
访问器,我们直接返回myVar
字段的值;对于set
访问器,我们将属性的值赋给myVar
字段。
三、字符串处理
1 C#4引用了动态类型
示例:高级C#技术(二)-CSDN博客
2 C#5引入了调用方法信息特性
举个例子:
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
方法的参数中,我们使用了CallerFilePath
、CallerLineNumber
和CallerMemberName
属性。这些属性会自动获取调用方的文件路径、行号和成员名称。在
Main
方法中调用LogMessage
方法时,会将参数传递给LogMessage
。当执行到LogMessage
方法时,你将看到输出的结果如下:
输出结果:
3 C#6引入了nameof 运算符用于获取变量类型方法和成员的名字
举个例子:
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引入了内插字符串字面量
举个例子:
class Myeven
{private int name;public int Name{get { return name; }set { name = value; }}public Myeven(){Console.WriteLine("姓名"+Name);Console.WriteLine($"姓名{Name}");}
}
只是部分内容分享其实还有很多我没有提及到