You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 10:15:47