C# 的一些关键高级特性

举报
Rolle 发表于 2024/10/31 22:43:02 2024/10/31
【摘要】 C# 是一种现代、通用、面向对象的编程语言,由微软在 .NET 平台上开发。自 2000 年首次发布以来,C# 已经发展出许多高级特性,使其成为开发各种应用程序的强大工具。本文将深入探讨 C# 的一些关键高级特性,并展示如何在实际编程中有效利用它们。异步编程与 async 和 await 关键字背景在现代应用程序中,异步编程非常重要,尤其是在处理 I/O 操作时,如读取文件、访问网络资源或与...

C# 是一种现代、通用、面向对象的编程语言,由微软在 .NET 平台上开发。自 2000 年首次发布以来,C# 已经发展出许多高级特性,使其成为开发各种应用程序的强大工具。本文将深入探讨 C# 的一些关键高级特性,并展示如何在实际编程中有效利用它们。

  1. 异步编程与 async 和 await 关键字
    背景
    在现代应用程序中,异步编程非常重要,尤其是在处理 I/O 操作时,如读取文件、访问网络资源或与数据库交互。同步操作可能导致应用程序的 UI 无响应,从而影响用户体验。

async 和 await 简介
C# 5.0 引入了 async 和 await 关键字,使异步编程变得更加直观和易于实现。async 标记一个方法为异步方法,而 await 则用于等待异步操作的完成。

示例代码
public async Task<string> GetDataFromUrlAsync(string url)
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string data = await response.Content.ReadAsStringAsync();
return data;
}
}
在上述代码中,GetDataFromUrlAsync 方法被标记为异步方法,并使用 await 关键字等待 HttpClient 异步操作的完成。这种写法不仅简化了代码,还能有效避免阻塞主线程。

  1. LINQ(语言集成查询)
    背景
    数据处理是大多数应用程序的核心部分。传统的数据处理方式通常涉及大量的循环和条件判断,而这些代码往往难以阅读和维护。

LINQ 简介
LINQ(Language Integrated Query)是 C# 中用于数据查询和操作的强大工具。它允许开发者使用查询语法直接在 C# 代码中进行数据操作,从而提高代码的可读性和可维护性。

示例代码
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evenNumbers = from number in numbers
where number % 2 == 0
select number;

foreach (var num in evenNumbers)
{
Console.WriteLine(num);
}
在上述代码中,LINQ 查询用于筛选出列表中的偶数,并通过 foreach 循环打印出来。LINQ 提供了一种声明式的方式来处理数据,使代码更加简洁和直观。

  1. 泛型(Generics)
    背景
    在许多情况下,我们希望编写能够处理不同类型数据的通用代码。在没有泛型的情况下,这通常通过使用 object 类型和类型转换来实现,但这会带来性能开销和类型安全问题。

泛型简介
泛型允许我们定义类型参数,从而编写与类型无关的代码。这不仅提高了代码的重用性,还能在编译时提供类型检查,从而避免运行时错误。

示例代码
public class GenericList<T>
{
private List<T> _list = new List<T>();

public void Add(T item)
{
    _list.Add(item);
}

public T Get(int index)
{
    return _list[index];
}

}
在上述代码中,GenericList<T> 是一个泛型类,它可以存储任意类型的对象。通过使用类型参数 T,我们可以创建类型安全且高效的集合类。

  1. 反射(Reflection)
    背景
    反射是指在运行时检查和操作类型信息的能力。它在许多高级编程任务中非常有用,例如动态类型创建、序列化和依赖注入。

反射简介
C# 提供了一组强大的反射 API,使开发者能够在运行时获取类型信息、调用方法和访问属性。

示例代码
public void PrintProperties(object obj)
{
Type type = obj.GetType();
PropertyInfo[] properties = type.GetProperties();
foreach (var property in properties)
{
Console.WriteLine($"{property.Name} = {property.GetValue(obj)}");
}
}
在上述代码中,PrintProperties 方法使用反射获取对象的所有属性,并打印它们的名称和值。这展示了如何使用反射在运行时动态操作对象。

  1. 表达式树(Expression Trees)
    背景
    表达式树是一种能够表示代码结构的树状数据结构。它在编译时生成,可以在运行时解析和执行。表达式树在动态语言实现、LINQ 提供程序和规则引擎等领域非常有用。

表达式树简介
C# 提供了一组 API,用于创建、修改和编译表达式树。通过表达式树,开发者可以在运行时生成并执行代码,从而实现高度动态化的应用程序。

示例代码
Expression<Func<int, int, int>> add = (a, b) => a + b;
Func<int, int, int> compiledAdd = add.Compile();
int result = compiledAdd(2, 3);
Console.WriteLine(result); // 输出 5
在上述代码中,我们创建了一个表示加法操作的表达式树,并将其编译成可执行的委托。表达式树使得我们能够在运行时生成和执行代码,从而实现更灵活的编程模型。

  1. 委托和事件
    背景
    委托是 C# 中的一种类型安全的函数指针,允许开发者将方法作为参数传递。事件是基于委托的一种特殊机制,用于在对象之间实现松散耦合的消息传递。

委托和事件简介
委托和事件使得开发者能够编写灵活的代码,实现回调和发布-订阅模式。委托定义了方法签名,而事件则允许对象订阅和响应特定的操作。

示例代码
public delegate void Notify(); // 定义委托

public class Process
{
public event Notify ProcessCompleted; // 定义事件

public void StartProcess()
{
    Console.WriteLine("Process Started!");
    // 模拟过程
    Thread.Sleep(2000);
    OnProcessCompleted();
}

protected virtual void OnProcessCompleted()
{
    ProcessCompleted?.Invoke();  // 触发事件
}

}

public class Program
{
public static void Main(string[] args)
{
Process process = new Process();
process.ProcessCompleted += Process_ProcessCompleted; // 订阅事件
process.StartProcess();
}

private static void Process_ProcessCompleted()
{
    Console.WriteLine("Process Completed!");
}

}
在上述代码中,我们定义了一个 Notify 委托和一个 ProcessCompleted 事件。在 Process 类中,当进程完成时触发 ProcessCompleted 事件,并在 Program 类中订阅该事件,从而实现事件驱动的编程模型。

  1. 属性(Properties)
    背景
    属性是 C# 中的一种特殊成员,提供了对字段的受控访问。它们使得我们能够在访问字段时添加额外的逻辑,例如验证和变更通知。

属性简介
属性使用 get 和 set 访问器定义,分别用于读取和写入属性值。属性的语法类似于字段,但提供了更多的控制和灵活性。

示例代码
public class Person
{
private string _name;

public string Name
{
    get { return _name; }
    set
    {
        if (string.IsNullOrEmpty(value))
            throw new ArgumentException("Name cannot be null or empty");
        _name = value;
    }
}

}
在上述代码中,Name 属性通过 get 访问器和 set 访问器提供对 _name 字段的受控访问。set 访问器中包含验证逻辑,以确保名称不为空。

  1. 可空类型(Nullable Types)
    背景
    在实际开发中,我们经常需要处理可能为空的值。传统的值类型(如 int、double)不能直接表示空值,导致我们不得不使用额外的标志位或特殊值来处理这种情况。

可空类型简介
C# 提供了可空类型(Nullable Types),使得值类型能够表示空值。可空类型使用 Nullable<T> 结构或简写形式 T? 表示。

示例代码
int? optionalValue = null;

if (optionalValue.HasValue)
{
Console.WriteLine($“Value: {optionalValue.Value}”);
}
else
{
Console.WriteLine(“Value is null”);
}
在上述代码中,optionalValue 是一个可空的 int 类型,可以存储 null。通过 HasValue 属性,我们可以检查可空

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。