C#类属性Getter和Setter写法是否正确?求规范写法指导
你的C#属性与Cloneable实现分析与修正
咱们一步步拆解你的代码问题,先从属性写法说起,再聊Cloneable接口的实现优化:
一、属性写法的合理性问题
首先看你的Name属性,这里存在逻辑不一致的明显问题:
get方法完全没用到私有变量_name,而是返回Id + "/" + Code的计算值set方法却把值存到_name里,但这个值永远不会被读取到
这会导致怪异的行为:当你给Name赋值后,读取Name时得到的依然是Id/Code,完全忽略了你设置的内容。得根据你的实际需求调整,有两种修正方向:
1. 如果Name是计算属性(仅由Id和Code推导)
那它应该是只读的,不需要set方法和私有变量_name,写法可以简化:
public string Name { get { return Id == null ? null : $"{Id}/{Code}"; } }
2. 如果Name需要独立存储值
那get方法应该返回存储的_name,而不是计算值,同时保留你的判重逻辑:
private string _name; public string Name { get { return _name; } set { if (_name != value) _name = value; } }
如果同时需要基于Id和Code的派生值,可以新增一个单独的只读属性,比如DerivedName。
另外,IsValid属性可以简化成更简洁的表达式写法:
public bool IsValid => Id != null;
二、Cloneable接口的实现优化
你的Clone实现思路是可行的,但有几个可以优化的点:
1. 强类型返回更友好
ICloneable的Clone方法默认返回object,你可以通过显式实现接口+强类型方法的方式,让调用更方便:
// 显式实现ICloneable接口 object ICloneable.Clone() => Clone(); // 强类型的Clone方法,外部调用更直观 public Element Clone() { var elem = new Element(); SetPropertyValues(elem); return elem; }
2. 反射逻辑的优化
- 你在
Where里已经过滤了CanWrite的属性,所以foreach里的if (property.CanWrite)判断是多余的,可以直接去掉 - 如果类的属性不会频繁变动,建议缓存反射得到的
PropertyInfo集合,避免每次Clone都重新反射,提升性能:private static readonly PropertyInfo[] _writableProperties = typeof(Element).GetProperties() .Where(p => p.CanWrite && (p.PropertyType.IsValueType || p.PropertyType.IsEnum || p.PropertyType == typeof(string))) .ToArray(); private void SetPropertyValues(Element elem) { foreach (var property in _writableProperties) { property.SetValue(elem, property.GetValue(this)); } }
3. 浅拷贝vs深拷贝
当前的实现是浅拷贝,对于值类型、字符串(不可变引用类型)来说没问题,但如果后续添加了自定义引用类型属性,需要考虑是否要实现深拷贝——这时候反射的方式就不够了,得手动处理那些引用类型的Clone逻辑。
4. 替代方案:手动复制属性
如果类的属性数量不多,手动复制比反射更高效、更直观,比如:
public Element Clone() { return new Element { Id = this.Id, Code = this.Code, // 注意:如果Name是计算属性,不需要复制,新对象会自己计算 // 如果Name是存储属性,这里复制this.Name即可 }; }
这种方式没有反射的性能开销,也更易维护。
修正后的完整代码示例
假设你选择把Name设为计算属性,最终代码可以是这样:
public class Element : ICloneable { public int? Id { get; set; } public string Code { get; set; } // 计算属性,只读 public string Name => Id == null ? null : $"{Id}/{Code}"; public bool IsValid => Id != null; // 显式实现ICloneable object ICloneable.Clone() => Clone(); // 强类型Clone方法 public Element Clone() { var elem = new Element(); SetPropertyValues(elem); return elem; } private static readonly PropertyInfo[] _writableProperties = typeof(Element).GetProperties() .Where(p => p.CanWrite && (p.PropertyType.IsValueType || p.PropertyType.IsEnum || p.PropertyType == typeof(string))) .ToArray(); private void SetPropertyValues(Element elem) { foreach (var property in _writableProperties) { property.SetValue(elem, property.GetValue(this)); } } }
内容的提问来源于stack exchange,提问作者user11735291
相关产品推荐
相关产品推荐

