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

时间:2015-10-20 15:04:34

标签: c# .net

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

这是一段示例代码:

为什么这样做:

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为公共成员包装器?

5 个答案:

答案 0 :(得分:5)

  

为什么这样?

由于在C#3.0中添加了自动实现的属性,因此没有理由。它可能是遗留代码,没有改变,旧习惯,或与C#3前代码保持一致。

  

这样就够了吗?

不 - 您已将virtual属性转换为非虚拟属性。所以它们并不完全等同。

等价物是

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

另外,为什么虚拟公共成员包装器?

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

  

缩短的表格何时会产生影响?

当类的内部代码(可以在编译时检测到)或通过反射访问它们(在运行时无法检测到,或通过静态代码分析)访问后备字段时)。

“自动实现”属性实际上获得了编译器创建的支持字段,因此在这种意义上,如果引用支持字段的唯一位置是在属性代码中,则它们是等效的。

答案 1 :(得分:3)

你有两个问题。首先是将属性更改为auto implemented properties,它们应该相同,但您删除了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;
        }
    }
}

答案 2 :(得分:2)

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

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

public string EmpName { get; set; }

只是编译器的捷径

private string _EmpName;
public string EmpName { 
    get{ return _EmpName;}
    set(_EmpName = value; }
}
它们在功能上完全相同。 但是,有些事情可以让捷径不让你做,例如你想在房产改变时举起一个事件。

还有你使用Virtual这是一个继承修饰符 虚拟指示它需要查看DOWN继承树的代码以获得更新的实现。 所以在

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

答案 3 :(得分:1)

看起来像这种形式的代码:

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

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

对于您显示的代码,拥有等效代码完全有效:

public virtual $type $var { get; set; }

您可以覆盖自动实现的属性并添加支持字段,验证以及必要时的任何内容。

答案 4 :(得分:0)

扩展形式是传统方式:

public class MyClass
{
    int _myInt;

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

然而,较短的形式被称为&#34;自动属性&#34;,在C#3.0中引入。

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

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

要考虑的一件事:您无法使用自动属性制作内部变量protected,因此如果您创建了一个派生类并且override属性,那么您就可以了需要使用base.MyProperty来访问它,或使用展开的表单。