C#中如何使用仅可读(get-only)属性且不添加set访问器?
问题描述
我创建了一个Device类,属性定义如下:
public int Id { get; } public string DeviceName { get; set; } public string MACAddress { get; set; } public string UUID { get; set; } public string SerialNumber { get; set; } public string Location { get; set; } public string PinCode { get; }
我通过这些属性从数据库获取设备信息,之后想用以下代码更新数据库中的设备:
private void _updateDeviceInDataBase() { DataAccess database = new DataAccess(); Device device = new Device() { DeviceName = textBox_PcNumber.Text, SerialNumber = DeviceProperties.GetSerialNumber(), UUID = DeviceProperties.GetUUID(), MACAddress = DeviceProperties.GetMACAddress(), Location = comboBox_Location.Text, }; database.UpdateDevice(device); }
现在的问题是,Id和PinCode属性为空,因为没法在device实例中直接设置它们,但我不想给这两个属性添加set访问器,请问该如何在device对象中使用这两个属性?
可行方案
1. 给Device类添加带参数的构造函数
直接在Device类里加个包含Id和PinCode的构造函数,创建实例时把这两个值传进去就行:
public class Device { public int Id { get; } public string DeviceName { get; set; } public string MACAddress { get; set; } public string UUID { get; set; } public string SerialNumber { get; set; } public string Location { get; set; } public string PinCode { get; } // 新增带参数的构造函数 public Device(int id, string pinCode) { Id = id; PinCode = pinCode; } // 要是需要无参构造,也可以保留(可选) public Device() { } }
然后修改更新代码,提前拿到要更新设备的Id和PinCode(比如从之前查询数据库的结果里取),创建实例时传入:
private void _updateDeviceInDataBase() { DataAccess database = new DataAccess(); // 假设你已经拿到了目标设备的Id和PinCode int targetDeviceId = 123; string targetPinCode = "ABC123"; Device device = new Device(targetDeviceId, targetPinCode) { DeviceName = textBox_PcNumber.Text, SerialNumber = DeviceProperties.GetSerialNumber(), UUID = DeviceProperties.GetUUID(), MACAddress = DeviceProperties.GetMACAddress(), Location = comboBox_Location.Text, }; database.UpdateDevice(device); }
2. 先查数据库拿完整的Device实例再更新
更新操作本来就应该基于数据库里已有的完整设备对象,你可以先根据Id从数据库查出对应的Device(自带Id和PinCode),再修改它的可写属性,最后调用更新:
private void _updateDeviceInDataBase() { DataAccess database = new DataAccess(); // 目标设备的Id,比如从界面或之前的查询结果获取 int targetDeviceId = 123; // 先获取完整的设备对象 Device existingDevice = database.GetDeviceById(targetDeviceId); // 更新可修改的属性 existingDevice.DeviceName = textBox_PcNumber.Text; existingDevice.SerialNumber = DeviceProperties.GetSerialNumber(); existingDevice.UUID = DeviceProperties.GetUUID(); existingDevice.MACAddress = DeviceProperties.GetMACAddress(); existingDevice.Location = comboBox_Location.Text; // 执行更新 database.UpdateDevice(existingDevice); }
这种方式最稳妥,不会遗漏任何必要属性,也符合更新操作的常规逻辑。
3. 用内部set访问器(限同一程序集)
如果DataAccess和Device类在同一个程序集里,可以把Id和PinCode的访问器改成internal set,这样同一程序集内的DataAccess能设置它们,但外部代码改不了:
public int Id { get; internal set; } public string PinCode { get; internal set; }
这种情况下你不用改当前的实例创建代码,而是让DataAccess在处理更新时负责填充这两个值,前提是你能控制DataAccess的逻辑。
4. 用工厂方法封装实例创建
在Device类里加个静态工厂方法,用来创建带Id和PinCode的实例,本质是把构造逻辑封装起来:
public class Device { // 属性定义不变 public static Device CreateDevice(int id, string pinCode) { return new Device(id, pinCode); } }
然后创建实例时调用这个方法:
Device device = Device.CreateDevice(targetDeviceId, targetPinCode) { DeviceName = textBox_PcNumber.Text, // 其他属性赋值 };
内容的提问来源于stack exchange,提问作者wads
相关产品推荐
相关产品推荐

