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

C#中init属性与仅get属性的区别及适用场景

C#中init属性与仅get属性的区别及适用场景

先看你给出的示例代码:

public class Person
{
    public string Name { get; init; }
    public string Family { get; }
}

这两个属性看似都是只读,但实际使用和赋值规则有明显差异,下面具体拆解:

核心差异:赋值时机与场景

1. 仅get属性({ get; })

这种属性的赋值权限非常严格:

  • 只能在类的构造函数或者字段初始化器中赋值
  • 对象实例创建完成后,完全无法修改该属性的值

示例代码:

public class Person
{
    // 字段初始化器赋值
    public string Family { get; } = "DefaultFamily";

    // 构造函数赋值
    public Person(string family)
    {
        Family = family;
    }
}

// 正确用法:通过构造函数初始化
var person1 = new Person("Smith");
// 错误:实例创建后无法修改,编译报错
// person1.Family = "Johnson";

2. init属性({ get; init; })

这种属性是C# 9.0引入的,兼顾了不可变性和初始化灵活性:

  • 除了构造函数、字段初始化器,还支持在对象初始化器中赋值
  • 一旦对象构造完成(离开初始化上下文),就再也无法修改该属性

示例代码:

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

// 正确用法:通过对象初始化器赋值
var person2 = new Person { Name = "Alice" };
// 错误:实例创建后无法修改,编译报错
// person2.Name = "Bob";

适用场景选择

用仅get属性的情况

  • 当属性是对象的核心标识或不可变依赖,必须在创建时就确定,绝对不允许后续修改(比如用户ID、订单编号)
  • 类的设计要求严格的不可变性,所有属性值都必须通过构造函数传入,避免任何意外修改的可能

用init属性的情况

  • 你需要保持对象的不可变性,但又不想写大量构造函数重载,希望用更简洁的对象初始化器语法创建实例(尤其是属性较多时)
  • 配合record类型使用时,init属性能很好地支持with表达式进行对象克隆修改(比如var newPerson = oldPerson with { Name = "Bob" })

混合使用示例

实际开发中经常会混合两种属性,兼顾核心不可变性和初始化灵活性:

public class Person
{
    // 核心ID必须通过构造函数赋值,绝对不可改
    public string Id { get; }
    // 基础信息可以通过初始化器赋值,实例创建后不可改
    public string Name { get; init; }
    public int Age { get; init; }

    public Person(string id)
    {
        Id = id;
    }
}

// 使用方式:构造函数传核心ID,初始化器补全其他属性
var person = new Person("user_123") { Name = "Charlie", Age = 30 };

内容的提问来源于stack exchange,提问作者Roohallah Azizi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 10:10:06