首页 文章

{get; set;}和访问修饰符

提问于
浏览
7

我刚刚开始学习c#,而且我对getter和setter的简写有点挣扎 .

据我了解,下面的两种方法是等效的 . 它是否正确?

//Method 1
public string name { get; set; }

//Method 2
private string name
public string getName() { return name;}
public string setName(string newName) { this.name = newName; }

其次,如果我们想要getter / setter和实例变量上的不同访问修饰符,这是如何工作的 . 以下代码错误,告诉我访问者必须比属性更具限制性,并且我不能为烦恼的访问器指定修饰符 . 有人可以澄清一下吗?

private int maxTime { public get; public set; }

编辑:澄清,我没有具体的目标,只有理解 . 我不明白这个简写符号是做什么的 . 在其他语言中,我有私有实例变量,并使用公共getter和setter来管理这些实例变量 . 如果我自己写出方法,它就允许这样做,但不是用这个简写符号 . 为什么是这样?

编辑2:检查我的理解的最后一个问题 . 下面的两个代码片段都使用属性来管理maxTime变量 . 两者之间的唯一区别是风格 . 它是否正确?

private int maxTime;
public int MaxTime{ get; set; }

VS

private int maxTime;

public int MaxTime
{
    get { return maxTime; }
    set { maxTime= value; }
}

5 回答

  • 2
    //Method 1
    public string name { get; set; }
    
    //Method 2
    public string name
    public string getName() { return name;}
    public string setName(string newName) { this.name = newName; }
    

    以上两种方法相当于 not .

    比较它们会更准确:

    //Method 1
    public string name { get; set; }
    
    //Method 2
    private string name; // this is private, not public.
    public string Name // this is a property, not a method.
    {
        get
        {
            return this.name;
        }
        set
        {
            this.name = value;
        }
    }
    

    如果你想玩访问修饰符,比如使 get 为public, set 为private,那么你会这样做:

    public int maxTime { get; private set; }
    

    关于Auto-Implemented Properties的更多信息以及幕后发生的编译器魔术 .

  • 1

    您可以编写一个将填充私有字段的属性,而不是错误的 private int maxTime { public get; public set; }

    private int maxTime;
    
    public int MaxTime
    {
        get { return maxTime; }
        set { maxTime = value; }
    }
    

    当您想要获取或设置maxTime的值时应用逻辑时,这非常有用 . 如果没有,一个简单的速记属性将做:

    public int MaxTime { get; set; }
    

    您可以创建一个具有公共getter但私有setter的属性,如下所示:

    public int MaxTime { get; private set; }
    

    这对于只读属性很有用,通常该属性在类的构造函数中填充 .

    你甚至可以创建一个属性,其中setter是公共的,但是getter是私有的,尽管我无法想象这会有用的任何场景 . 而且,代码标准声称这样的东西应该是一种方法,而不是一种 property . (read this)

    public int MaxTime { private get; set; }
    

    编辑2中你的问题的答案是否定的 .

    第一个代码永远不会改变私有int maxTime ,而第二个代码确实如此 . 但是,如果你的 class 只使用属性 MaxTime ,那么它们在功能上是等价的 .

    更新:

    从c#6开始,你可以在没有setter的情况下编写速记属性:

    public int MaxTime {get;}
    

    这些属性只能在构造函数中初始化,或者硬编码如下:(也是c#6的新功能)

    public int MaxTime {get;} = DateTime.Now;
    

    这对于不可变属性很有用(与readonly属性不同,这样的属性的值在初始化后甚至在托管类内部也不会改变 .

  • 14

    当您使用方法1中的属性(公共字符串名称{get; set;})时,编译器会自动生成私有后备字符串变量以及公共getter和setter方法 .

    一般的想法是将字段设为私有,并且只允许通过公共getter / setter方法进行访问 . 因此,如果使用方法2,则声明变量private .

    我建议使用ILDASM来仔细阅读生成的IL,它有助于了解幕后发生了什么 .

    第二个错误就是编译器所说的 . 构造的可见性必须一致

  • 6
    public string name { get; set; }
    

    你所拥有的是Auto-Implemented property,它内部有一个支持私有字段(以及get / set的编译时方法) .

    在C#代码中,这相当于:

    private string _name;
    public string name
    {
        get { return _name; }
        set { _name = value; }
    }
    

    在编译时,get / set被转换为方法调用,有点类似于你所拥有的 .

    对于:

    private int maxTime { public get; public set; }
    

    错误很明显,您不能拥有比属性本身更少限制的访问说明符 . 例如,如果您希望 public 属性具有 public get ,但如果您只想允许在类中设置属性,则可以执行以下操作:

    public int maxTime { get; private set; }
    

    您还应该看到:.Net Naming conventions,如果您遵循这一点会更好,因此您可以将您的属性名称以大写字母开头 .

  • 3

    第一种方法是C#语法糖,用于自动实现的属性 . 当您编译它时,它提供适当的访问器的实现 .

    第二个例子是不同的 . 在这里,您有一个公共范围字段(通常是因为封装原则而禁止使用)和两个访问变量的方法 . 有's a subtle difference in semantic usage; typically properties are used to expose state, whereas a method normally indicates that the method has some computation behind it and isn' t只是返回或更改当前状态(同样,这是一个约定,而不是一个快速的规则)方法通常使用VerbAction命名(public Thing GetAThing(){}) .

    自动生成的属性可以具有不同的访问修饰符,但只能使得get或set的可访问性低于整体修饰符 .

    public int X { get; private set; } // OK
    public int X { private get; set; } // OK
    private int X { public get; public set; } // NOT OK
    

相关问题