C # 没有私有变量的自定义 getter/setter

我最近学习了 c # ,所以当我学习编写属性时,我被教导这样做:

public string Name { get; set; }

汽车属性是伟大的!但是现在我要做一些更复杂的事情,所以我需要编写一对定制的访问器。

private string _Name;
public string Name {
get { return _Name; }
set { _Name = value }
}

我知道当一个人使用 autos 时,编译器会在黑暗的深处创建一个私有实例变量,但是我被宠坏了,我不想让那个私有变量看起来毫无意义。

有没有不使用私有变量的自定义访问器的方法?

108912 次浏览

Properties don't need backing variables (fields) at all. While they can be used for encapsulating simple fields you can also use them to access other data.

public Decimal GrandTotal { get { return FreightTotal + TaxTotal + LineTotal; } }

or

public string SomeStatus { get { return SomeMethodCall(); } }

If the goal is to simply encapsulate some field with a property you would need some sort of backing field if you are not using automatic properties.

No, I'm afraid not. The compiler is smart enough to make this happen for you on auto-generated properties, but with standard properties I imagine the logic behind something like that would end up getting in the way and doing more harm than good.

For example, what if I create a property like this...

public int SomeValue
{
get
{
return 0;
}
}

Would the compiler (with the feature you're looking for) create a backing private variable? Why? It doesn't need one.

Additionally, if the private value isn't created until compilation time, what are you going to reference in your code:

public string Name {
get { return _Name; }
set { _Name = value }
}

What is _Name? What if you have another value somewhere else called _Name? Then what would the compiler call the backing value for this property? What if I need two backing values? Would the compiler be smart enough for that?

public string Name
{
get
{
return string.Format("{0} {1}", _FirstName, _LastName);
}
set
{
// some parsing magic
}
}

It's been asked before, but I imagine the answer is going to continue to be "no" for the foreseeable future.

An auto-property is syntactic shorthand for simple direct member access. (And I imagine one of its driving forces was simply to try to get people to stop creating public values directly.) Properties can grow in complexity well beyond that very easily and I personally wouldn't want the compiler trying to figure out what I can easily just tell it to do.

The answer is No, you cannot do that. It is because of recursion. (See line numbers 9 and 7):

Line 1  :   public string Name
Line 2  :   {
Line 3  :     get
Line 4  :     {
Line 5  :         return FirstName + " "  + LastName;
Line 6  :     }
Line 7  :     set
Line 8  :     {
Line 9  :         Name = value; // <-- Goes back to Line 7
Line 10 :     }
Line 11 :   }

I know this is an old question, but there is at least one other option here. I'm doing something similar to the below for my own app.

This might not exactly be for your use case, but it shows that a custom getter and setter can be used without a private instance variable. In this case, the getter and setter are shortcut or helper methods to access the Name property of the User for the Account.

We can let the value be set by doing Account.AccountUser.Name = "John Doe";, but sometimes that seems a bit clunky and it works against the idea of separation of concerns. Do we want someone using the Account class to know there's a User imbedded in it? If for some reason we don't, we now have a way to still update the User.Name even if we make AccountUser private.

In this case, AccountUser is public, but it doesn't have to be. When it's private, a Json or XML conversion utility (such as Newtonsoft) should ignore the AccountUser and show just the Name as if the Account were a flat model, instead of having multiple levels.

public class User
{
public int Id { get; set; }
public string Name { get; set; }
}


public class Account
{
public int Id { get; set; }
public User AccountUser { get; set; }
    

public string Name
{
get
{
return AccountUser.Name;
}


set
{
AccountUser.Name = value;
}
}
}