C#开发中是否应将所有Getter/Setter属性类型设为string?
你的写法确实是不良实践,但问题不在「把校验放在setter里」
你觉得把校验逻辑收敛在属性setter里更整洁的直觉是对的——属性setter中放合法性校验本身是非常标准的最佳实践,真正的问题是你为了接住控制台的字符串输入,强行把本应为数值类型的GPA属性定义成了string,属于典型的类型设计和职责划分错位。
这种写法的核心问题
- 首先是类型语义完全错配
GPA的本质是0-10区间的浮点数,不是字符串。把对外暴露的GPA属性设为string会带来大量无意义的额外成本:后续要做平均分计算、成绩排序、及格统计这类操作时,每次都要先把字符串转成double,还要反复处理转换失败的异常;同一个GPA值可能对应多种字符串写法(比如4.5、4.50、4.5(末尾带空格)),后续做值比较的时候很容易出现逻辑bug。 - 其次是职责边界混乱
你把两类完全不同的校验逻辑揉在了一起:- 属于
Student类本身的领域规则校验:比如姓名不能含数字、不能为空,GPA必须在0-10区间——这类校验放在setter里是完全正确的,不管数据来自控制台、接口请求还是数据库,只要给Student属性赋值就会自动校验,从根源上避免非法对象被创建。 - 属于交互层的输入格式校验:比如用户在控制台敲的一串字符能不能转成合法的double——这部分是主程序(输入/UI层)的职责,根本不该塞到Student类里。Student类不需要关心数据是从哪来的,它只需要接收符合自己类型定义的合法值即可。
- 属于
- 顺便提一句,你现在写的姓名校验逻辑还有bug:现有判断条件会允许全空格的姓名通过校验,且逻辑运算符的组合很容易出边界错误。
推荐的改法
把GPA属性改回double类型,setter里只保留数值范围的合法性校验,输入格式转换的逻辑移到主程序中处理即可。
修正后的Student类代码:
public class Student { private string name; private double gpa; internal string Name { get { return name; } set { if (!string.IsNullOrWhiteSpace(value) && value.All(c => !char.IsDigit(c))) { name = value; } else { throw new ArgumentException("Student's name is not valid"); } } } internal double GPA { get { return gpa; } set { if (value >= 0 && value <= 10) { gpa = value; } else { throw new ArgumentOutOfRangeException("Student's GPA must be between 0 and 10"); } } } public override string ToString() { return $"Student's name: {Name}\nStudent's GPA: {GPA}"; } }
调整后的主程序逻辑:
Student student = new Student(); while (true) { try { Console.WriteLine("Enter student's name: "); string nameInput = Console.ReadLine(); student.Name = nameInput; Console.WriteLine("Enter student's GPA: "); string gpaInput = Console.ReadLine(); // 输入层先处理格式转换校验,转换成功后再赋值给领域对象 if (!double.TryParse(gpaInput, out double gpaValue)) { Console.WriteLine("GPA input is not a valid number, please try again"); continue; } student.GPA = gpaValue; Console.WriteLine(student.ToString()); break; } catch (Exception e) { Console.WriteLine(e.Message); } }
这种写法的好处很明显:Student类完全不依赖控制台交互逻辑,后续你要做桌面端、Web端功能的时候,这个类可以直接复用;所有数值操作可以直接调用GPA属性,不需要反复做类型转换;错误边界也更清晰:输入格式错误由交互层提示,数值非法由对象校验拦截,不会把两类不同的错误混为一谈。
内容的提问来源于stack exchange,提问作者tr44nv
相关产品推荐
相关产品推荐

