为什么要为类中的私有成员创建公共包装器?

本文关键字:创建 包装 成员 为什么 | 更新日期: 2023-09-27 18:18:28

我一直有这个问题,但到目前为止我一直盲目地跟随。

这是一段示例代码:

为什么这样做:

public class EmployeeInfo
{
    int _EmpNo;
    public virtual int EmpNo
    {
        get { return _EmpNo; }
        set { _EmpNo = value; }
    }
    string _EmpName;
    public virtual string EmpName
    {
        get { return _EmpName; }
        set { _EmpName = value; }
    }
}

在获取/设置期间没有任何其他操作,例如计算或验证?

这就够了吗?

public class EmployeeInfo
{
    public int EmpNo { get; set; }
    public string EmpName { get; set; }
} 

另外,为什么公共成员包装器是virtual ?

为什么要为类中的私有成员创建公共包装器?

为什么这样做?

自从c# 3.0中添加了自动实现的属性后,真的没有理由这么做。它可能是未更改的遗留代码,旧习惯,或者与c# 3之前的代码保持一致。

这就够了吗?

No -你已经将virtual属性转换为非虚拟。所以它们不是完全等价的。

对应的是

public class EmployeeInfo
{
    public virtual int EmpNo { get; set; }
    public virtual string EmpName { get; set; }
} 

同样,为什么public成员包装器是virtual ?

以便派生类可以覆盖属性的逻辑—添加验证,更改通知等。

缩写形式在什么时候真正产生影响?

当后备字段被类的内部代码引用时(可以在编译时检测到),或者当它们被反射访问时(只有在运行时才能检测到,或者通过静态代码分析)。

一个"自动实现"的属性实际上得到一个由编译器创建的后备字段,所以在这个意义上,如果后备字段被引用的唯一地方是在属性代码中,它们是等价的。

你有两个问题。首先是将属性更改为自动实现的属性,它们应该是相等的,但是你删除了virtual关键字,这使得它们不同。

那么,virtual是什么?该关键字将允许派生类覆盖上述属性的get/set

参见:virtual c#

virtual关键字用于修改方法、属性、索引器或参数事件声明,并允许在派生类中重写 .

你的类与自动实现属性将是相等的,如果你有:

public class EmployeeInfo
{
    public virtual int EmpNo { get; set; }
    public virtual string EmpName { get; set; }
}

之后,你可以重写一个属性,让另一个属性保持父属性的行为,比如:

public class ManagerInfo : EmployeeInfo
{
    private int _EmpNo;
    public override int EmpNo
    {
        get { return _EmpNo; }
        set
        {
            if (value < 100) throw new Exception("EmpNo for manager must be greater than 100");
            _EmpNo = value;
        }
    }
}

取决于您是否想要公开查看该字段,

如果你只打算在声明类中使用字段,那么你不需要将其包装在属性中,只有当你需要公开或在继承树中公开它时,你才应该使用属性

public string EmpName { get; set; }

只是编译器

的快捷方式
private string _EmpName;
public string EmpName { 
    get{ return _EmpName;}
    set(_EmpName = value; }
}

它们在功能上相同。然而,有一些事情是快捷方式不允许你做的,例如,你想在属性改变时引发一个事件。

中还使用了Virtual,这是一个继承修饰符Virtual指示代码需要向下查看继承树以寻找更新的实现。所以在

class A
{
    public string Data
    {
        get{return "A";}
    }
    public virtual string VData
    {
        get{return "A";}
    }
}
class B:A
{
    public new string Data
    {
        get{return "B";}
    }
    public override string VData
    {
        get{return "B";}
    }
}

那么如果你做了

A obj = new B();
obj.Data; //return A
obj.VData; //return B

代码如下:

$type _$var;
public virtual $type $var
{
    get { return _$var; }
    set { _$var = value; }
}

是使用工具、模板或代码片段生成的。由于习惯几乎没有改变,工具、模板和代码片段几乎没有更新,我猜它们是在自动实现属性(public $type $var { get; set; })引入c#语言之前创建的。

对于您所展示的代码,使用等效的

是完全有效的:
public virtual $type $var { get; set; }

因为你可以覆盖自动实现的属性,并添加一个支持字段,验证和任何必要的

展开表单是传统的方式:

public class MyClass
{
    int _myInt;
    virtual public int MyProperty
    {
        get
        {
            return _myInt;
        }
        set
        {
            _myInt = value;
        }
    }
}

然而,较短的形式称为"auto properties",在c# 3.0中引入。

public class MyClass
{
    virtual public int MyProperty { get; set; }
}

这些代码块是等价的。这是保持代码简洁的好方法。

需要考虑的一件事:您不能使内部变量protected具有自动属性,因此,如果您创建了一个派生类并将override创建为您的属性,则需要使用base.MyProperty来访问它,或者使用扩展形式