You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过反射在同一C# record实例上批量赋值属性?

关于C# Record反射修改属性的问题解答

首先纠正一个关键误解:你代码中的Person record属性使用的是set访问器,这类属性本身是可变的,调用SetValue时并不会创建新实例——你看到的哈希码变化,是因为record的GetHashCode()是基于当前属性值计算的,属性值改变后哈希码自然更新,并非实例被替换。你可以通过object.ReferenceEquals对比引用,验证赋值前后始终是同一个实例。

针对不可变Record(使用init访问器)的反射修改

如果你的目标是真正的不可变Record(属性用init定义,编译时禁止直接修改),那么确实可以通过反射绕过编译约束,直接在原实例上修改多个属性,全程不会创建新实例——这和with关键字的行为(创建新实例并复制修改)完全不同。

示例代码如下:

public class Program
{
    public record Person
    {
        // 使用init访问器实现编译时不可变
        public string FirstName { get; init; }
        public string LastName { get; init; }
    }

    public static void Main()
    {
        var p = new Person { FirstName = "OriginalFirst", LastName = "OriginalLast" };
        Console.WriteLine($"原实例哈希码: {p.GetHashCode()}");
        Console.WriteLine($"原实例内容: {p}");

        // 获取所有公共实例属性
        var properties = p.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
        
        foreach (var prop in properties)
        {
            // 反射修改属性值,直接作用于原实例
            prop.SetValue(p, "Modified");
        }

        Console.WriteLine($"修改后实例哈希码: {p.GetHashCode()}");
        Console.WriteLine($"修改后实例内容: {p}");
        // 验证实例引用未变
        Console.WriteLine($"是否为同一实例: {object.ReferenceEquals(p, p)}"); // 始终为True
    }
}

核心结论

  • 若Record属性用set:属性本身支持直接修改,无论直接赋值还是反射操作,都不会创建新实例,哈希码变化仅因属性值更新。
  • 若Record属性用init:编译时无法直接修改,但反射可以在原实例上直接修改属性值,不会生成新实例,这正是你想要的批量修改效果。

内容的提问来源于stack exchange,提问作者Roi Shabtai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:01:19