Q1:当属性名与 field 关键字重名时,编译器如何消歧义?

深度解析:这是工程中最常见的命名冲突。C# 14 引入了上下文敏感的关键字处理机制。

public class UserProfile {
    private string field = "Old Data"; // 你的自定义字段

    public string Name {
        get => field; // 编译器优先识别为 C# 14 的“隐式后备字段”
        set {
            // 如果你想访问上面定义的私有变量 field,必须使用 this 或 @
            if (value == this.field) return; 
            
            // 这里的 field 指的是该属性底层的存储单元
            field = value; 
        }
    }
}

Q2:params ReadOnlySpan<T> 在异步状态机中的“逃逸”限制逻辑是什么?

深度解析:这是内存安全的核心。ref struct 严禁被装箱或存入堆。

// ❌ 编译错误:ReadOnlySpan 无法存入异步状态机类
public async Task ProcessAsync(params ReadOnlySpan<int> data) {
    await Task.Delay(1); 
    Console.WriteLine(data[0]); 
}

// ✅ 同步预处理
public async Task BetterProcessAsync(int[] data) {
    // 1. 在同步上下文中利用 Span 的零分配性能
    var sum = ComputeSum(data); 
    
    // 2. 然后再进入异步
    await Task.Delay(1);
}
private int ComputeSum(params ReadOnlySpan<int> span) => /* ... */;

Q3:扩展块(Extension Blocks)能否定义“虚成员”或支持多态?

深度解析不能。扩展成员本质上是静态绑定的(Static Dispatch),不是动态分发。

public interface ILogger { }
public extension LoggerExt for ILogger {
    public void LogInfo(string msg) => Console.WriteLine(msg);
}

// 即使子类重写了同名方法,如果通过 ILogger 接口调用,
// 永远执行的是 LoggerExt 里的版本。这与原生类成员的 virtual/override 逻辑完全不同。

Q4:field 关键字在多线程竞态条件下是否安全?

深度解析:隐式后备字段与普通字段在内存模型上一致。它不具备原子性。

public int Counter {
    get;
    set => field++; // ❌ 非线程安全。在高并发下会发生 Lost Update
}

// ✅ 正确做法:仍需配合锁或 Interlocked
public int SafeCounter {
    get;
    set => Interlocked.Increment(ref field); // field 关键字支持 ref 传递
}

Q5:扩展块如何改变“领域驱动设计 (DDD)”中贫血模型的现状?

深度解析:它允许我们在不修改实体(Entity)核心代码的前提下,为其注入特定上下文的业务逻辑,实现真正的“关注点分离”。

// Domain 层:纯粹的数据模型
public record Order(int Id, decimal Amount);

// WebAPI 层:注入展示逻辑,而不污染 Domain 层
public extension OrderDisplay for Order {
    public string DisplayPrice => $"CNY {this.Amount:N2}";
}

Q6:?.= 短路赋值在右侧包含“闭包捕获”时,内存表现如何?

深度解析:如果左侧为 null,右侧的闭包对象甚至不会被实例化。

// 如果 app 为 null,编译器生成的 IL 会直接跳过右侧。
// 意味着变量 'x' 的捕获和匿名对象的分配压根不会发生。
app?.Manager = new { Name = x, Time = DateTime.Now }; 

Q7:params 集合增强后,如何处理 T[]ReadOnlySpan<T> 的过载歧义?

深度解析:编译器有一套复杂的优先级评分系统。通常,显式的数组重载具有更高的向后兼容优先级。

void Call(params int[] arr) => Console.WriteLine("Array");
void Call(params ReadOnlySpan<int> span) => Console.WriteLine("Span");

// C# 14 中,如果你直接传入数组,会匹配到 Array 版本。
// 如果你想走零分配路径,可以显式强制转换或由编译器自动在热点路径优化。

Q8:partial 属性如何彻底解决 AOP(面向切面编程)的性能开销?

深度解析:传统 AOP 依赖反射或动态代理(如 Castle Core),性能损耗大。partial 属性让 AOP 在编译期完成。

// 开发者只写:
[AutoLog] 
public partial string SecretKey { get; set; }

// Source Generator 在另一个文件中生成:
public partial string SecretKey {
    get => field;
    set {
        Log($"Key changed from {field} to {value}");
        field = value;
    }
}

Q9:扩展操作符(Extension Operators)能否实现跨类型的强制转换?

深度解析:可以。这为处理旧系统中的“僵尸代码”提供了极佳的适配器方案。

public extension LegacyConverter for LegacyUser {
    // 将旧系统的 LegacyUser 隐式转换为新系统的 User 模型
    public static implicit operator User(LegacyUser legacy) => new User(legacy.Name);
}

Q10:field 关键字在 struct(值类型)中的内存对齐表现?

深度解析:编译器生成的隐式字段会遵循 [StructLayout(LayoutKind.Auto)], 在需要严格内存对齐(如高性能网络协议解析)的 struct 中,建议依然手动声明字段并配合 [FieldOffset],以确保内存布局的确定性。

// --- 手动控制布局(推荐高精场景) ---
public struct LegacyData {
    public byte Flag;    // 1 byte
    // 填充 3 bytes 以对齐 4 字节边界
    private int _value;  // 4 bytes
    public int Value { get => _value; set => _value = value; }
} // Total: 8 bytes

// --- C# 14 使用 field 关键字 ---
public struct ModernData {
    public byte Flag;    // 1 byte
    
    public int Value { 
        get; 
        set => field = value; // 编译器在此处插入 int 类型的隐式字段
    }
} // Total: 8 bytes (编译器依然会根据 Sequential 规则在 Flag 后填充 3 字节)

//如果该 struct 需要通过 stackalloc 或在高性能循环中大量使用,建议放弃 field,回归手动字段声明并加上 [StructLayout(LayoutKind.Explicit)]
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct Packet {
    [FieldOffset(0)] public byte Type;
    [FieldOffset(4)] private int _payload; // 显式控制偏移,确保没有多余 Padding
    
    public int Payload {
        get => _payload;
        set => _payload = value;
    }
}