我刚刚开始学习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来管理这些实例变量。如果我自己写出方法,它就允许这样做,但不能用这个简写符号。这是为什么?
EDIT2:检查我理解的最后一个问题。下面的两个代码片段都使用属性来管理maxTime变量。两者之间的唯一区别是风格。这是对的吗?
private int maxTime;
public int MaxTime{ get; set; }
VS
private int maxTime;
public int MaxTime
{
get { return maxTime; }
set { maxTime= value; }
}
答案 0 :(得分:14)
而不是错误的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; }
这对于readonly属性很有用,通常在类的构造函数中填充该属性。
你甚至可以创建一个属性,其中setter是公共的,但是getter是私有的,尽管我无法想象任何有用的场景。而且,代码标准声称这样的东西应该是一个方法,而不是一个属性。 (read this)
public int MaxTime { private get; set; }
编辑2中你的问题的答案是否定的。
第一个代码永远不会更改私有int maxTime
,而第二个代码确实如此。但是,如果您在课堂内只使用属性MaxTime
,那么它们在功能上是等效的。
更新
从c#6开始,你可以在没有setter的情况下编写速记属性:
public int MaxTime {get;}
这些属性只能在构造函数中初始化,或者硬编码如下:(也是c#6的新功能)
public int MaxTime {get;} = DateTime.Now;
这对于不可变属性非常有用(与readonly属性不同,这样的属性的值在初始化后甚至不会在托管类中更改。
答案 1 :(得分:6)
//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; }
以上两种方法 不 等效。
比较它们会更准确:
//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
设为公开,将set
设为私有,那么您可以这样做:
public int maxTime { get; private set; }
有关Auto-Implemented Properties的更多信息以及幕后发生的编译器魔法。
答案 2 :(得分:3)
final StringBuilder chars = new StringBuilder();
list.forEach(l -> chars.append(l.charAt(0)));
你所拥有的是Auto-Implemented property,它内部有一个支持私有字段(以及get / set的编译时方法)。
在C#代码中,这相当于:
public string name { get; set; }
在编译时,get / set被转换为方法调用,有点类似于你拥有的。
有关:
private string _name;
public string name
{
get { return _name; }
set { _name = value; }
}
错误很明显,您不能拥有比属性本身更少限制的访问说明符。例如,如果您希望private int maxTime { public get; public set; }
属性具有public
public
,但如果您只想允许在类中设置属性,则可以执行以下操作:
get
您还应该看到:.Net Naming conventions,如果您遵循这一点会更好,因此您可以将您的属性名称以大写字母开头。
答案 3 :(得分:2)
第一种方法只是C#语法糖,用于自动实现的属性。当您编译它时,它提供了相应访问器的实现。
第二个例子不同。在这里,您有一个公共范围字段(通常是因为封装原则而禁止使用)和两个访问变量的方法。语义使用方面存在细微差别;通常属性用于暴露状态,而方法通常表示该方法背后有一些计算并且不会返回或改变当前状态(再次,这是一个约定,而不是一个快速的规则)方法通常使用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
答案 4 :(得分:1)
当您使用方法1中的属性(公共字符串名称{get; set;})时,编译器会自动生成私有后备字符串变量以及公共getter和setter方法。
一般的想法是将字段设为私有,并且只允许通过公共getter / setter方法进行访问。因此,如果您使用方法2,则声明变量private。
我建议使用ILDASM仔细阅读生成的IL,这有助于了解幕后发生的事情。
第二个错误就是编译器所说的。构造的可见性必须一致