我已经查看了与字段相比的属性示例,我总是看到一个没有解释的事情是创建私有字段,然后创建属性。为什么我们需要_foo
,并且不能只运行与我下面相似的代码,或者可以用Foo = Foo
替换Foo = value
?
我在运行时看到它创建了一个堆栈溢出异常,所以我猜它正在寻找一个值来填充Foo
或value
,但我认为这将是当我def.Foo = 55
时处理。
即使创建私有字段是最佳做法,我仍然希望更好地了解实际导致溢出的内容。
class ABC
{
private int _foo; //Why create this?
public int Foo
{
get { return Foo; }
set
{
Foo = Foo;//more logic would go here. }
}
}
}
class Program
{
static void Main(string[] args)
{
ABC def = new ABC();
def.Foo = 55;
Console.WriteLine($"The value of Foo is {def.Foo}.");
Console.ReadLine();
}
}
答案 0 :(得分:1)
这是因为字段和属性不一样。
private int _foo; //field
public int Foo //property
{
get { return _foo; } //should be _foo
set
{
_foo = value;
}
}
通常,您使用公共财产来访问私有字段,因为您可能想要执行除分配/获取值之外的其他操作该领域。
示例:
private bool selectedIndexChanged; //note this additional field
public bool SelectedIndexChanged {
get { return selectedIndexChanged; }
set { selectedIndexChanged = value; }
}
private int selectedIndex; //Why create this?
public int SelectedIndex
{
get { return selectedIndex; }
set
{
selectedIndexChanged = value != selectedIndex; //you update selectedIndexChanged here!
selectedIndex = value;
}
}
请注意,您不直接访问私有字段,但可以通过公共属性访问它们。拥有属性的好处在于,您不仅可以读取/分配字段值,还可以执行其他内容:检查输入的有效性,分配其他字段,调用事件等等......
即使创建私有字段是最佳做法,我仍然会这样做 希望更好地了解实际造成的问题 溢出。
练习导致 错误 导致 溢出 >练习:
private int _foo; //Why create this?
public int Foo
{
get { return Foo; } //this should not happen, wrong practice
set
{
Foo = Foo; //neither should this happen, another wrong practice
}
}
以上代码中发生的事情是:
同样地:
因此导致溢出......
答案 1 :(得分:1)
为什么我们需要_foo,而且不能只运行类似于我的代码 有以下,或可能取代?
因为属性是方法,可以设置或获取字段的值。所以,你必须先定义一个字段。如果您必须在内部暗示任何逻辑,尤其是在setter中,则需要这样做。否则,使用自动实现的属性更为常见。
即使在我们使用自动实现属性的情况下,编译器也会为我们生成一个支持字段。
public Person
{
public string FirstName { get; set; }
}
例如,这样做
var person = new Person { FirstName = "Bob" };
使用名为Person
的属性创建一个新的FirstName
对象,其类型为字符串。此外,您将人员FirstName
的值设置为Bob。这是你必须要注意的一点。编译器会生成一个类型为string的后备字段,并且在运行时,这将是存储对该人的名字的引用的地方。
上述类的定义类似于以下类:
public Person
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
}
实际上,当您定义自动实现的属性时,幕后的编译器是什么。基于此,我们可以说对字符串“Bob”的引用将存储到_firstName
。
答案 2 :(得分:0)
属性实际上是实际变量的get / set方法。但是,您并不总是需要私有变量来拥有一个属性。
你可以简单地拥有
public int Foo { get; set; }
编译器将为您创建和设置变量。 但是,如果您需要限制属性以获取分配的错误值或执行其他任务,则需要属性变量。
示例:
private int _score;
public int Score
{
get { return _score; }
set
{
if(value > 100)
throw new Exception("Score cannot be more than 100");
_score = value;
}
}