C# 最新版本特性介绍

概述

C# 作为微软开发的现代编程语言,一直在不断进化,以适应快速变化的技术需求。每个新版本的发布都带来了许多新特性和改进,使得开发者能够更高效地编写代码,同时提升应用程序的性能和安全性。本教程将详细介绍 C# 最新版本的特性,帮助你了解这些新功能,并学会如何在实际项目中应用它们。

环境搭建

在开始学习 C# 最新版本的特性之前,首先需要确保你的开发环境已经配置好。我们推荐使用 Visual Studio 和 .NET SDK 来编写和运行 C# 程序。

安装 Visual Studio

  1. 访问 Visual Studio 官网 下载最新版本的 Visual Studio。
  2. 安装时选择“.NET 桌面开发”工作负载。

安装 .NET SDK

  1. 访问 .NET 官网 下载最新版本的 .NET SDK。
  2. 按照安装向导完成安装。

创建第一个 C# 程序

在 Visual Studio 中创建一个新的 C# 控制台应用程序项目,编写一个简单的“Hello World”程序来验证环境是否配置正确。

using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

基本语法和数据类型

C# 的基本语法和数据类型是编程的基础。以下是一些常用的数据类型:

  • int:整数类型
  • double:双精度浮点数
  • string:字符串
  • bool:布尔类型
int age = 30;
double height = 1.75;
string name = "John Doe";
bool isStudent = true;

变量、常量和运算符

变量

变量用于存储数据,可以在程序运行时改变其值。

int count = 10;
count = 20; // 变量的值可以改变

常量

常量在声明后不能改变其值。

const int MAX_COUNT = 100;
// MAX_COUNT = 200; // 错误,常量不能被修改

运算符

C# 支持多种运算符,包括算术运算符、比较运算符和逻辑运算符。

int a = 10;
int b = 20;
int sum = a + b; // 算术运算符
bool isEqual = a == b; // 比较运算符
bool isTrue = (a < b) && (a != 0); // 逻辑运算符

面向对象编程 (OOP) 基础

面向对象编程是一种编程范式,通过类和对象来组织代码。

类和对象

类是对象的蓝图,对象是类的实例。

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public void Greet()
    {
        Console.WriteLine($"Hello, my name is {Name} and I am {Age} years old.");
    }
}

Person person = new Person { Name = "Alice", Age = 25 };
person.Greet();

继承和多态

继承允许一个类继承另一个类的属性和方法,多态允许子类以不同的方式实现父类的方法。

class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Animal makes a sound");
    }
}

class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Dog barks");
    }
}

Animal myDog = new Dog();
myDog.MakeSound(); // 输出 "Dog barks"

接口和抽象类

接口

接口定义了一组方法和属性的签名,但不提供实现。

interface IShape
{
    double Area();
}

class Circle : IShape
{
    public double Radius { get; set; }

    public double Area()
    {
        return Math.PI * Radius * Radius;
    }
}

抽象类

抽象类可以包含抽象方法和具体方法,不能直接实例化。

abstract class Shape
{
    public abstract double Area();
}

class Square : Shape
{
    public double SideLength { get; set; }

    public override double Area()
    {
        return SideLength * SideLength;
    }
}

命名空间和程序集

命名空间用于组织代码,避免命名冲突。程序集是编译后的代码单元。

namespace MyNamespace
{
    class MyClass
    {
        // 类定义
    }
}

泛型

泛型允许你编写可以处理不同数据类型的代码。

class GenericClass<T>
{
    public T Value { get; set; }
}

GenericClass<int> intInstance = new GenericClass<int> { Value = 10 };
GenericClass<string> stringInstance = new GenericClass<string> { Value = "Hello" };

委托和事件

委托

委托是一种类型安全的函数指针,可以引用方法。

delegate void MyDelegate(string message);

void ShowMessage(string message)
{
    Console.WriteLine(message);
}

MyDelegate myDelegate = ShowMessage;
myDelegate("Hello, delegate!");

事件

事件是基于委托的,用于实现发布-订阅模式。

class Publisher
{
    public event MyDelegate MyEvent;

    public void RaiseEvent()
    {
        MyEvent?.Invoke("Event raised!");
    }
}

Publisher publisher = new Publisher();
publisher.MyEvent += ShowMessage;
publisher.RaiseEvent();

LINQ (Language Integrated Query)

LINQ 提供了一种统一的查询语法,可以用于查询集合数据。

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = from num in numbers
                  where num % 2 == 0
                  select num;

foreach (var num in evenNumbers)
{
    Console.WriteLine(num);
}

异步编程 (async/await)

异步编程允许你编写非阻塞的代码,提高应用程序的响应性。

async Task<int> DownloadDataAsync()
{
    await Task.Delay(1000); // 模拟下载数据
    return 42;
}

async Task MainAsync()
{
    int result = await DownloadDataAsync();
    Console.WriteLine($"Downloaded data: {result}");
}

反射和特性

反射

反射允许你在运行时检查和操作对象的类型信息。

Type type = typeof(MyClass);
Console.WriteLine(type.FullName);

特性

特性用于为代码元素添加元数据。

[Obsolete("This method is deprecated.")]
void OldMethod()
{
    // 方法实现
}

值类型和引用类型

值类型

值类型直接存储数据,存储在栈上。

int x = 10;
int y = x; // y 是 x 的副本

引用类型

引用类型存储对象的引用,存储在堆上。

MyClass obj1 = new MyClass();
MyClass obj2 = obj1; // obj2 引用 obj1

垃圾回收机制

垃圾回收器自动管理内存,回收不再使用的对象。

void CreateObjects()
{
    MyClass obj = new MyClass();
    // obj 在方法结束时超出作用域,垃圾回收器会回收它
}

使用 using 语句管理资源

using 语句确保资源在使用后被正确释放。

using (StreamReader reader = new StreamReader("file.txt"))
{
    string content = reader.ReadToEnd();
    Console.WriteLine(content);
}

性能优化技巧

避免不必要的装箱和拆箱

装箱将值类型转换为引用类型,拆箱反之。

int number = 42;
object boxedNumber = number; // 装箱
int unboxedNumber = (int)boxedNumber; // 拆箱

使用 StringBuilder 处理字符串拼接

字符串拼接频繁时,使用 StringBuilder 提高性能。

StringBuilder sb = new StringBuilder();
sb.Append("Hello");
sb.Append(" ");
sb.Append("World");
string result = sb.ToString();

内存泄漏防范

内存泄漏通常是由于未释放的资源或循环引用导致的。

class MyClass
{
    public MyClass Reference { get; set; }
}

void CreateCycle()
{
    MyClass obj1 = new MyClass();
    MyClass obj2 = new MyClass();
    obj1.Reference = obj2;
    obj2.Reference = obj1; // 循环引用
}

文件 I/O 操作

文件 I/O 操作允许你读写文件。

void WriteFile(string filePath, string content)
{
    File.WriteAllText(filePath, content);
}

void ReadFile(string filePath)
{
    string content = File.ReadAllText(filePath);
    Console.WriteLine(content);
}

序列化和反序列化

序列化将对象转换为字节流,反序列化反之。

[Serializable]
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

void SerializeObject(Person person, string filePath)
{
    IFormatter formatter = new BinaryFormatter();
    using (Stream stream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
    {
        formatter.Serialize(stream, person);
    }
}

Person DeserializeObject(string filePath)
{
    IFormatter formatter = new BinaryFormatter();
    using (Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
    {
        return (Person)formatter.Deserialize(stream);
    }
}

数据库访问 (ADO.NET, Entity Framework)

ADO.NET

ADO.NET 提供了一组类来访问数据库。

void ExecuteQuery(string connectionString, string query)
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        SqlCommand command = new SqlCommand(query, connection);
        connection.Open();
        SqlDataReader reader = command.ExecuteReader();
        while (reader.Read())
        {
            Console.WriteLine(reader["ColumnName"]);
        }
    }
}

Entity Framework

Entity Framework 是一个 ORM 框架,简化了数据库访问。

class MyDbContext : DbContext
{
    public DbSet<Person> People { get; set; }
}

class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

void AddPerson(Person person)
{
    using (MyDbContext context = new MyDbContext())
    {
        context.People.Add(person);
        context.SaveChanges();
    }
}

XML 和 JSON 处理

XML

XML 是一种标记语言,用于存储和传输数据。

void ParseXml(string xml)
{
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xml);
    XmlNode node = doc.SelectSingleNode("//NodeName");
    Console.WriteLine(node.InnerText);
}

JSON

JSON 是一种轻量级的数据交换格式。

void ParseJson(string json)
{
    JObject obj = JObject.Parse(json);
    string value = (string)obj["KeyName"];
    Console.WriteLine(value);
}

正则表达式

正则表达式用于模式匹配。

void MatchPattern(string input, string pattern)
{
    Regex regex = new Regex(pattern);
    Match match = regex.Match(input);
    if (match.Success)
    {
        Console.WriteLine("Match found: " + match.Value);
    }
}

Windows Forms 基础

Windows Forms 是用于创建桌面应用程序的 UI 框架。

class MyForm : Form
{
    public MyForm()
    {
        Button button = new Button();
        button.Text = "Click me";
        button.Click += Button_Click;
        Controls.Add(button);
    }

    private void Button_Click(object sender, EventArgs e)
    {
        MessageBox.Show("Button clicked!");
    }
}

WPF (Windows Presentation Foundation)

WPF 是用于创建现代桌面应用程序的 UI 框架。

<Window x:Class="MyWPFApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="Click me" Click="Button_Click"/>
    </Grid>
</Window>
namespace MyWPFApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button clicked!");
        }
    }
}

XAML 基础

XAML 是一种声明性语言,用于定义 WPF 应用程序的用户界面。

<Window x:Class="MyWPFApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="Click me" Click="Button_Click"/>
    </Grid>
</Window>

数据绑定

数据绑定将 UI 元素与数据源关联。

<Window x:Class="MyWPFApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBox Text="{Binding Name}"/>
    </Grid>
</Window>
namespace MyWPFApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new Person { Name = "John Doe" };
        }
    }

    class Person
    {
        public string Name { get; set; }
    }
}

控件和布局

WPF 提供了丰富的控件和布局选项。

<Window x:Class="MyWPFApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <Button Content="Button 1"/>
            <Button Content="Button 2"/>
        </StackPanel>
    </Grid>
</Window>

ASP.NET Core 简介

ASP.NET Core 是一个跨平台的 Web 开发框架。

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();