C# Custom getter/setter without private variable

C#Coding StyleAccessorAutomatic Properties

C# Problem Overview


I learned c# recently, so when I learned to write properties, I was taught to do it like this:

public string Name { get; set; }

Auto properties are great! But now I'm trying to do something a little more complicated, so I need to write a custom pair of accessors.

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

I know the compiler makes a private instance variable down in it's murky depths when one uses autos, but I'm spoiled and don't want that private variable sitting around looking pointless.

Is there a way to use custom accessors without a private variable?

C# Solutions


Solution 1 - C#

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.

Solution 2 - C#

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 :   }

Solution 3 - C#

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.

Solution 4 - C#

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;
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTin CanView Question on Stackoverflow
Solution 1 - C#jhappoldtView Answer on Stackoverflow
Solution 2 - C#tikaView Answer on Stackoverflow
Solution 3 - C#DavidView Answer on Stackoverflow
Solution 4 - C#computercarguyView Answer on Stackoverflow