跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C Sharp 只读属性
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C#只读属性 = == 介绍 == 在C#中,'''只读属性'''(Read-only Property)是一种特殊类型的属性,它允许外部代码获取属性的值,但不允许修改该值。只读属性通常用于封装类的内部状态,确保数据的不可变性(immutability),从而提高代码的安全性和可维护性。 只读属性可以通过以下方式实现: * 使用'''get'''访问器而不提供'''set'''访问器 * 使用'''init'''访问器(C# 9.0引入,允许对象初始化期间赋值) * 使用'''readonly'''字段作为属性支持字段 == 基本语法 == 以下是只读属性的基本语法: <syntaxhighlight lang="csharp"> public class Person { // 只读属性(传统方式) public string Name { get; } // 只能在构造函数或声明时初始化 // 使用init访问器(C# 9.0+) public int Age { get; init; } // 可在构造函数或对象初始化器中赋值 public Person(string name, int age) { Name = name; Age = age; } } </syntaxhighlight> == 详细说明 == === 传统只读属性 === 传统只读属性(仅有get访问器)的值只能在构造函数或声明时设置: <syntaxhighlight lang="csharp"> public class Circle { public double Radius { get; } // 只读属性 public Circle(double radius) { Radius = radius; // 只能在构造函数中赋值 } public double Area => Math.PI * Radius * Radius; // 计算属性 } </syntaxhighlight> === 使用init访问器 === C# 9.0引入的init访问器提供了更灵活的只读属性初始化方式: <syntaxhighlight lang="csharp"> public class Product { public string Id { get; init; } // 可在对象初始化器中赋值 public string Name { get; init; } // 使用示例: // var p = new Product { Id = "P001", Name = "Laptop" }; // 之后不能再修改Id和Name } </syntaxhighlight> === 计算型只读属性 === 只读属性也可以是基于其他字段或属性计算得出的值: <syntaxhighlight lang="csharp"> public class Rectangle { public double Width { get; set; } public double Height { get; set; } // 计算型只读属性 public double Area => Width * Height; // 使用示例: // var rect = new Rectangle { Width = 10, Height = 5 }; // Console.WriteLine(rect.Area); // 输出50 } </syntaxhighlight> == 实际应用场景 == === 不可变对象 === 只读属性常用于创建不可变对象,这在多线程环境中特别有用: <syntaxhighlight lang="csharp"> public class ImmutablePoint { public int X { get; } public int Y { get; } public ImmutablePoint(int x, int y) { X = x; Y = y; } // 方法返回新实例而不是修改现有实例 public ImmutablePoint Move(int dx, int dy) => new(X + dx, Y + dy); } </syntaxhighlight> === 配置对象 === 只读属性适合用于配置对象,确保配置一旦设置就不能被意外修改: <syntaxhighlight lang="csharp"> public class AppSettings { public string DbConnectionString { get; init; } public int MaxRetryCount { get; init; } public bool EnableLogging { get; init; } // 使用示例: // var settings = new AppSettings { // DbConnectionString = "Server=...", // MaxRetryCount = 3, // EnableLogging = true // }; } </syntaxhighlight> == 性能考虑 == 只读属性通常不会引入显著的性能开销。对于简单的属性访问,JIT编译器通常会内联(inline)这些调用。然而,对于计算密集型属性,应考虑缓存结果: <syntaxhighlight lang="csharp"> public class ExpensiveCalculation { private double? _cachedResult; private readonly double _input; public double Result { get { if (_cachedResult == null) { // 模拟耗时计算 _cachedResult = Enumerable.Range(0, 1000000) .Select(i => Math.Pow(_input, i) / Factorial(i)) .Sum(); } return _cachedResult.Value; } } private static double Factorial(int n) => n <= 1 ? 1 : n * Factorial(n - 1); public ExpensiveCalculation(double input) => _input = input; } </syntaxhighlight> == 与只读字段的比较 == 只读属性与readonly字段有相似之处,但存在重要区别: {| class="wikitable" |- ! 特性 !! 只读属性 !! readonly字段 |- | 可访问性 | 可以有各种访问修饰符 | 只能通过字段访问控制 |- | 计算能力 | 可以包含计算逻辑 | 只能是存储的值 |- | 接口实现 | 可以实现接口属性 | 不能直接实现接口成员 |- | 序列化 | 通常被序列化器支持 | 可能需要特殊处理 |} == 高级主题 == === 只读属性的反射 === 通过反射可以绕过只读属性的限制,但应谨慎使用: <syntaxhighlight lang="csharp"> public class ReadOnlyDemo { public string Value { get; } = "Initial"; public static void ModifyReadOnlyProperty() { var obj = new ReadOnlyDemo(); Console.WriteLine(obj.Value); // 输出"Initial" var prop = typeof(ReadOnlyDemo).GetProperty("Value"); prop.SetValue(obj, "Modified"); Console.WriteLine(obj.Value); // 输出"Modified" } } </syntaxhighlight> === 只读接口属性 === 接口可以定义只读属性,实现类可以选择如何实现: <syntaxhighlight lang="csharp"> public interface IReadOnlyData { string Data { get; } // 只读接口属性 } public class DataImplementation : IReadOnlyData { public string Data { get; } = "Fixed Data"; } public class ComputedData : IReadOnlyData { public string Data => DateTime.Now.ToString(); // 每次访问计算新值 } </syntaxhighlight> == 最佳实践 == * 优先使用只读属性而不是公共字段 * 对于真正的不可变对象,使用只读属性和readonly字段的组合 * 考虑使用init访问器来提供更灵活的对象初始化方式 * 对于计算密集型属性,考虑缓存结果 * 避免通过反射修改只读属性,除非有充分理由 == 总结 == C#只读属性是创建安全、不可变对象的重要工具。它们提供了一种封装数据的方式,同时确保数据不会被意外修改。从简单的值封装到复杂的计算属性,只读属性在C#编程中有广泛的应用。随着C#语言的演进(如init访问器的引入),只读属性的使用变得更加灵活和强大。 [[Category:编程语言]] [[Category:C Sharp]] [[Category:C Sharp 属性与事件]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)