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

C# WinForm中为何ProductionWorker实例无法访问其受保护自动属性

权限报错的核心原因
  • C#中protected修饰符的访问边界非常明确:被该标记的类成员,只能在类自身的内部代码、以及该类的所有派生类的内部代码中访问。你的Form1是独立的窗体类,既不属于Employee/ProductionWorker的内部实现,也不是这两个类的派生类,直接通过worker.Name这类外部实例访问的方式,必然触发无权限提示。
  • 自动实现属性只是帮你生成私有后备字段的语法糖,完全不会改变成员本身的访问级别,不存在“绕过protected限制”的可能。
  • 代码中还存在一个容易被忽略的bug:你在ProductionWorker类里重复声明了和基类同名的Name、Numberprotected属性,这会直接隐藏基类的同名字段。构造函数中给基类传参赋值的是基类的两个字段,你重复声明的那两个同名字段全程没有被赋值,就算权限问题解决,读到的也会是默认空值。
合规的实现方案

按照作业要求,Employee的Name/Number、ProductionWorker的ShiftNum/PayRate必须保持protected访问级别,不能直接改成public。常规的封装式解决思路是:在类内部新增公共的只读访问入口——这类入口写在类的内部实现里,天然有权限读取自身的protected成员,既不违反作业的访问级别要求,也能让外部代码正常获取属性值:

  1. 删掉ProductionWorker里重复定义的Name、Number属性,这两个成员直接从基类继承即可,无需重复声明。
  2. 在Employee基类中,保留原有两个protected属性不动,新增无副作用的公共只读方法,对外暴露读取能力。
  3. 在ProductionWorker类中,保留自身两个protected属性不动,新增对应的公共只读方法。
  4. 修改Form1中的取值逻辑,改为调用这些公共方法获取属性值,不要直接访问protected成员。
修正后的代码示例
// Employee基类
class Employee
{
    // 严格按照作业要求保持protected访问级别
    protected string Name { get; set; }
    protected int Number { get; set; }

    // 新增公共只读访问入口,不改变核心属性的访问级别
    public string GetName() => Name;
    public int GetNumber() => Number;

    public Employee(string name, int number)
    {
        Name = name;
        Number = number;
    }
}

// ProductionWorker派生类
class ProductionWorker : Employee
{
    // 严格按照作业要求保持protected访问级别
    protected int ShiftNum { get; set; }
    protected double PayRate { get; set; }

    // 新增公共只读访问入口
    public int GetShiftNum() => ShiftNum;
    public double GetPayRate() => PayRate;

    public ProductionWorker(string Name, int Number, int shiftNum, double payRate) : base(Name, Number)
    {
        ShiftNum = shiftNum;
        PayRate = payRate;
    }
}

// Form1中修改后的取值逻辑
private void button2_Click(object sender, EventArgs e)
{
    ProductionWorker worker = new ProductionWorker(textBox1.Text, 
                                                   Convert.ToInt32(textBox2.Text),
                                                   Convert.ToInt32(textBox3.Text),
                                                   Convert.ToDouble(textBox4.Text));
    textBox5.Text = $"Name: {worker.GetName()}\n Number: {worker.GetNumber()}\n Shift Number: {worker.GetShiftNum()}\n Hourly Pay Rate: {worker.GetPayRate()}";
}

补充说明:这种封装方式也是面向对象设计的常规做法,相比直接把属性设为public,既保证了内部存储字段的访问可控性,也满足了外部代码的读取需求,完全符合课程作业对访问级别的要求。

内容的提问来源于stack exchange,提问作者spabsa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 03:24:03