C# 9 新特性:init 关键字探索

在C# 9中,随着.NET 5的发布,迎来了一个有趣的新关键字:init。这个关键字允许开发者创建不可变对象,至少在标记了init的属性方面是不可变的,从而确保这些属性的值在初始化后不会被改变。本文将深入探讨init关键字的工作原理以及如何使用它。

首先,来看init关键字的基本用法。在声明属性时,可以使用init关键字代替set关键字,如下所示: class TestClass1 { public int TestClass1IntProperty { get; set; } } class TestClass2 { public int TestClass2IntProperty { get; init; } } 在上面的例子中,TestClass1的TestClass1IntProperty属性是可变的,而TestClass2的TestClass2IntProperty属性则是不可变的。

接下来,来看如何使用这些属性: void Main() { TestClass1 test1 = new TestClass1 { TestClass1IntProperty = 42 }; test1.TestClass1IntProperty = 43; // 这是允许的,因为属性是可变的。 TestClass2 test2 = new TestClass2 { TestClass2IntProperty = 42 }; // 下面的代码将导致编译错误: // CS8852 Init-only property or indexer '' // can only be assigned to an object initializer, // or on 'this' or 'base' in an instance constructor or an 'init' accessor. test2.TestClass2IntProperty = 43; } 如上所示,尝试修改TestClass2的TestClass2IntProperty属性将导致编译错误,因为它是不可变的。

此外,可以在类中只对某些属性使用init关键字,以达到部分不可变的目的,如下所示: class TestClass3 { public int TestClass3IntProperty { get; set; } public int TestClass3IntProperty2 { get; init; } } 在这种情况下,TestClass3的TestClass3IntProperty属性是可变的,而TestClass3IntProperty2属性则是不可变的。

还可以通过在初始化实例时运行自定义代码来设置属性值,如下所示: class TestClass4 { private int _testClass4IntProperty; public int TestClass4IntProperty { get => _testClass4IntProperty; init => _testClass4IntProperty = value; } private int _testClass4IntProperty2; public int TestClass4IntProperty2 { get => _testClass4IntProperty2; init { _testClass4IntProperty2 = value; } } } 在这个例子中,TestClass4的TestClass4IntProperty和TestClass4IntProperty2属性在初始化时可以执行自定义代码。

尽管init关键字非常有用,但它也有一些需要注意的事项。例如,如果属性是引用类型,那么它只保持引用,而不是对象本身,这意味着仍然可以修改引用对象的非不可变属性,如下所示: class TestClass5 { public int TestClass5IntProperty { get; set; } } class TestClass6 { public TestClass5 TestClass6RefProperty { get; init; } } void Main() { TestClass6 test = new TestClass6 { TestClass6RefProperty = new TestClass5 { TestClass5IntProperty = 42 } }; test.TestClass6RefProperty.TestClass5IntProperty = 445; // 这是有效的,因为没有改变引用。 test.TestClass6RefProperty = new TestClass5 { TestClass5IntProperty = 13 }; // 这将导致错误,因为试图改变init属性的引用。 } 在这个例子中,尽管TestClass6的TestClass6RefProperty属性是不可变的,但仍然可以修改引用对象的非不可变属性。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485