404 Not Found

404 Not Found


nginx

高级特性概览

反射(Reflection)

反射允许程序在运行时检查和操作自身的类型信息。Type 类是反射的核心,通过它可以获取字段、属性、方法等元数据。

获取类型信息

CSHARP
using System;
using System.Reflection;

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public void SayHello() => Console.WriteLine("Hello!");
}

class Program
{
    static void Main()
    {
        Type type1 = typeof(Person);
        Type type2 = new Person().GetType();

        Console.WriteLine($"类型名: {type1.Name}");

        Console.WriteLine("属性:");
        foreach (PropertyInfo p in type1.GetProperties())
            Console.WriteLine($"  {p.Name} ({p.PropertyType.Name})");

        Console.WriteLine("方法:");
        foreach (MethodInfo m in type1.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
            Console.WriteLine($"  {m.Name}");
    }
}
TEXT
类型名: Person
属性:
  Name (String)
  Age (Int32)
方法:
  get_Name
  set_Name
  get_Age
  set_Age
  SayHello

动态创建实例

CSHARP
using System;
using System.Reflection;

class Dog
{
    public string Breed { get; set; } = "Unknown";
    public override string ToString() => $"Dog: {Breed}";
}

class Program
{
    static void Main()
    {
        Type type = typeof(Dog);
        object obj = Activator.CreateInstance(type)!;

        PropertyInfo prop = type.GetProperty("Breed")!;
        prop.SetValue(obj, "Husky");

        Console.WriteLine(obj);
    }
}
TEXT
Dog: Husky

示例

CSHARP
using System;
using System.Linq;
using System.Reflection;

class Calculator
{
    public int Add(int a, int b) => a + b;
    public double Multiply(double x, double y) => x * y;
    public void Reset() { }
}

class Program
{
    static void Main()
    {
        Calculator calc = new Calculator();
        Type type = calc.GetType();

        Console.WriteLine($"类型: {type.Name}");
        Console.WriteLine($"命名空间: {type.Namespace}");
        Console.WriteLine($"是否为类: {type.IsClass}");

        Console.WriteLine("公共方法:");
        MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        foreach (MethodInfo m in methods)
        {
            string parameters = string.Join(", ", m.GetParameters().Select(p => $"{p.ParameterType.Name} {p.Name}"));
            Console.WriteLine($"  {m.ReturnType.Name} {m.Name}({parameters})");
        }
    }
}
▶ 试一试
TEXT
类型: Calculator
命名空间: 
是否为类: True
公共方法:
  Int32 Add(Int32 a, Int32 b)
  Double Multiply(Double x, Double y)
  Void Reset()

Attribute 特性

特性是用于为代码元素添加元数据的声明性标签。可使用内置特性或自定义特性。

内置特性

CSHARP
using System;

class LegacyService
{
    [Obsolete("请使用 NewService 代替", error: false)]
    public void OldMethod() => Console.WriteLine("旧方法");

    public void NewMethod() => Console.WriteLine("新方法");
}

class Program
{
    static void Main()
    {
        var service = new LegacyService();
        service.OldMethod();
        service.NewMethod();
    }
}
TEXT
旧方法
新方法
💡 Obsoleteerror 参数设为 true 时,调用旧方法将产生编译错误而非警告。

自定义特性

CSHARP
using System;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
class DescriptionAttribute : Attribute
{
    public string Text { get; }
    public DescriptionAttribute(string text) => Text = text;
}

[Description("用户管理服务")]
class UserService
{
    [Description("获取所有用户")]
    public void GetAll() { }
}

class Program
{
    static void Main()
    {
        var attr = Attribute.GetCustomAttribute(typeof(UserService), typeof(DescriptionAttribute)) as DescriptionAttribute;
        Console.WriteLine(attr?.Text ?? "无描述");
    }
}
TEXT
用户管理服务

泛型约束深入

泛型约束通过 where 关键字限制类型参数的范围,确保类型参数满足特定条件。

约束类型一览

约束 说明
where T : class T 必须是引用类型
where T : struct T 必须是值类型(不可为 null)
where T : new() T 必须有无参公共构造函数
where T : ISpecific T 必须实现指定接口
where T : BaseClass T 必须继承指定基类
where T : unmanaged T 必须是非托管类型
where T : notnull T 必须是不可为 null 的类型

示例

CSHARP
using System;

interface IRepository
{
    string GetName();
}

class SqlRepository : IRepository
{
    public string GetName() => "SQL Repository";
}

class Service<T> where T : class, IRepository, new()
{
    private T _repo = new T();
    public void Print() => Console.WriteLine(_repo.GetName());
}

class Program
{
    static void Main()
    {
        var service = new Service<SqlRepository>();
        service.Print();
    }
}
▶ 试一试
TEXT
SQL Repository
⚠️ new() 约束必须放在约束列表的最后,classstruct 应放在最前。

迭代器(yield)

迭代器使用 yield return 逐个生成序列元素,实现惰性求值——元素仅在迭代时才计算。

yield return 与 yield break

CSHARP
using System;
using System.Collections.Generic;

class Program
{
    static IEnumerable<int> GetNumbers()
    {
        for (int i = 0; i < 5; i++)
        {
            if (i == 3) yield break;
            yield return i;
        }
    }

    static void Main()
    {
        foreach (int n in GetNumbers())
            Console.WriteLine(n);
    }
}
TEXT
0
1
2
💡 yield break 立即终止迭代。迭代器方法返回 IEnumerable<T>IEnumerator<T>

示例

CSHARP
using System;
using System.Collections.Generic;

class Program
{
    static IEnumerable<int> Fibonacci(int count)
    {
        int a = 0;
        int b = 1;
        for (int i = 0; i < count; i++)
        {
            yield return a;
            int temp = a + b;
            a = b;
            b = temp;
        }
    }

    static void Main()
    {
        Console.WriteLine("斐波那契数列前10项:");
        foreach (int n in Fibonacci(10))
        {
            Console.Write(n + " ");
        }
        Console.WriteLine();
    }
}
▶ 试一试
TEXT
斐波那契数列前10项:
0 1 1 2 3 5 8 13 21 34 

Span<T> 与 Memory<T>

Span<T>Memory<T> 提供对连续内存区域的无拷贝切片访问,是高性能场景的关键类型。

Span<T> 基本用法

CSHARP
using System;

class Program
{
    static void Main()
    {
        int[] array = { 10, 20, 30, 40, 50 };
        Span<int> span = array.AsSpan();
        Span<int> slice = span.Slice(1, 3);

        slice[0] = 99;

        Console.WriteLine(string.Join(", ", array));

        Span<int> stackSpan = stackalloc int[3];
        stackSpan[0] = 1;
        stackSpan[1] = 2;
        stackSpan[2] = 3;
        Console.WriteLine(string.Join(", ", stackSpan.ToArray()));
    }
}
TEXT
10, 99, 30, 40, 50
1, 2, 3
⚠️ Span<T> 只能存储在栈上,不能作为类字段或跨 await 使用。需要跨栈帧时使用 Memory<T>

正则表达式(Regex)

System.Text.RegularExpressions.Regex 类用于模式匹配、搜索和替换文本。

常用操作

CSHARP
using System;
using System.Text.RegularExpressions;

class Program
{
    static void Main()
    {
        string input = "联系电话: 138-1234-5678, 邮箱: test@example.com";

        bool hasPhone = Regex.IsMatch(input, @"\d{3}-\d{4}-\d{4}");
        Console.WriteLine($"包含电话: {hasPhone}");

        Match phoneMatch = Regex.Match(input, @"\d{3}-\d{4}-\d{4}");
        Console.WriteLine($"电话: {phoneMatch.Value}");

        MatchCollection emails = Regex.Matches(input, @"[\w.]+@[\w.]+");
        foreach (Match m in emails)
            Console.WriteLine($"邮箱: {m.Value}");

        string replaced = Regex.Replace(input, @"\d{4}", "****");
        Console.WriteLine($"替换: {replaced}");
    }
}
TEXT
包含电话: True
电话: 138-1234-5678
邮箱: test@example.com
替换: 联系电话: 138-**-**, 邮箱: test@example.com

常用模式速查

模式 说明
\d 数字
\w 字母/数字/下划线
\s 空白字符
. 任意字符(除换行)
^ / $ 行首 / 行尾
{n,m} 重复 n 到 m 次
[abc] 字符集

不安全代码(unsafe)

unsafe 上下文允许使用指针和手动内存操作,适用于互操作或极致性能场景。

指针与 fixed

CSHARP
using System;

class Program
{
    static unsafe void Main()
    {
        int value = 42;
        int* ptr = &value;

        Console.WriteLine($"值: {*ptr}");
        Console.WriteLine($"地址: {(long)ptr}");

        int[] arr = { 1, 2, 3 };
        fixed (int* p = arr)
        {
            Console.WriteLine($"首元素: {*p}");
            Console.WriteLine($"第二元素: {*(p + 1)}");
        }
    }
}
TEXT
值: 42
地址: 12345678
首元素: 1
第二元素: 2
⚠️ 使用 unsafe 需要在项目文件中启用 <AllowUnsafeBlocks>true</AllowUnsafeBlocks>fixed 语句固定对象防止 GC 移动内存。

C# 版本特性一览(7~12)

版本 关键特性 简要说明
C# 7 out 变量、元组、模式匹配 out int x 内联声明,(int, string) 元组,is Type 模式
C# 7 本地函数、ref 返回 方法内嵌套函数,引用返回值
C# 8 可空引用类型、异步流 string? 可空标注,IAsyncEnumerable<T>
C# 8 默认接口方法、索引与范围 接口默认实现,[^1][1..3]
C# 9 记录类型、init 设置器 record 不可变类型,init 只初始化属性
C# 9 顶级语句、目标类型 new 无需 Main 模板,new() 省略类型
C# 10 global using、文件范围命名空间 global using X;namespace Ns; 单行
C# 10 记录结构体、const 插值字符串 record struct,常量内插字符串
C# 11 原始字符串字面量、required """...""" 多行原始串,required 强制初始化
C# 11 列表模式、UTF8 字面量 [1, 2, ..] 匹配,"hello"u8
C# 12 主构造函数 class C(int x) 类声明即构造
C# 12 集合表达式、别名任意类型 [1, 2, 3] 统一初始化,using P = int*
💡 本课为高级特性概览,每个主题后续均有独立课程深入讲解。

❓ 常见问题

Q 反射有性能开销吗?
A 有,反射比直接调用慢数十倍,频繁使用应缓存 MethodInfo 或改用表达式树。 Q:Span&lt;T> 和 Memory&lt;T> 有何区别? A:Span 只能存于栈,不可跨 async/存储;Memory 可存于堆,可跨异步边界,通过 .Span 访问。 Q:yield return 是多线程的吗? A:不是,yield 是单线程的惰性枚举机制,元素在 MoveNext() 调用时才计算。 Q:什么时候需要 unsafe 代码? A:需要与 C/C++ 互操作、操作非托管内存或追求极致性能时使用,日常开发应避免。

📖 小节

  • 反射通过 Type 类在运行时获取类型元数据并动态创建实例
  • Attribute 为代码添加声明性元数据,支持自定义与运行时读取
  • 泛型约束(where)限制类型参数为引用类型、值类型、有构造函数等
  • yield return 实现惰性迭代,yield break 终止枚举
  • Span<T> 提供栈上零拷贝切片,Memory<T> 可跨异步边界
  • Regex 类支持模式匹配、搜索、替换等文本操作
  • unsafe 上下文允许指针操作,需 fixed 固定内存
  • C# 7~12 持续引入元组、可空引用、记录类型、主构造函数等特性

📝 作业

  1. 使用反射获取 string 类的所有公共方法名称并输出
  2. 创建一个自定义 [Author] 特性,标注在类上并通过反射读取
  3. 编写一个泛型方法 T Create<T>() where T : new(),创建并返回实例
  4. 用 yield return 实现一个生成斐波那契数列前 20 项的迭代器
  5. 使用 Regex 验证一个字符串是否为合法的 IPv4 地址格式
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏