82

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?

Tin Can
  • 2,540
  • 2
  • 29
  • 39
  • 21
    No. it's not possible. – Bala R Dec 20 '11 at 15:16
  • 1
    Yes! Create a private auto property! JK. What exactly are you trying to do - what's that your 'custom accessors' would be doing that doesn't require a private property? – YetAnotherUser Dec 20 '11 at 15:17
  • 1
    What do you mean by "custom accessors" exactly? What's "custom" about them? – Oded Dec 20 '11 at 15:18
  • 3
    @Oded I think by "custom", he means all non-auto properties. – Bala R Dec 20 '11 at 15:19
  • Why is it not possible! how about `public string Age { get {return 16;} set{doNothingWithThis(value);}}`. It's possible - don't know how useful it would be though? – YetAnotherUser Dec 20 '11 at 15:20
  • How does the private variable "look pointless" if it's being used? – David Dec 20 '11 at 15:20
  • @BalaR - He might mean different accessibility for getters vs setters. – Oded Dec 20 '11 at 15:23
  • Accessor is used to access a variable, so the answer would be no – StaWho Dec 20 '11 at 15:25
  • Just in case anyone actually was wondering by custom I mean, (I'm not sure what I meant when I wrote this a whole HOUR ago because the answer is so clear now, I digress) I mean I needed to do exactly what Josh Happoldt's answer suggested, run a couple of method calls to see what the property should look like – Tin Can Dec 20 '11 at 16:04
  • @Bala-R. Simple great Answer. +1 for making a comment sound louder than answers listed below. – Ravi Nov 12 '14 at 19:46
  • 4
    A better approach to this problem is tracked here: https://github.com/dotnet/csharplang/issues/133 – Sachin Joseph Apr 14 '18 at 21:12

4 Answers4

62

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.

jhappoldt
  • 2,406
  • 1
  • 21
  • 24
  • +1 If you compare the .NET implementation of properties to a language like Java, you realize that the `get` and `set` is just shorthand for creating two different methods called `get_PropertyName` and `set_PropertyName` – Kyle Trauberman Dec 20 '11 at 15:29
  • well, conceptually sure. technically, defining 2 methods with those names (in C# at least) doesn't result in a property you can see with reflection. Wish we could for my current desire (marking only the setter as obsolete). – Maslow Apr 03 '17 at 14:32
32

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 :   }
tika
  • 7,135
  • 3
  • 51
  • 82
  • 2
    Right, if you call the getter/setter inside itself it would cause infinite recursion. The C# compiler, internally, creates a backing field for properties. This is sometimes called the instance variable in other languages. In objective-c, for example, by declaring `name`, you also get `_name`. – Tin Can Mar 15 '17 at 13:23
  • Would this even happen if i check for modification first? i.e. set { if (Name != value) Name = value } – Sandro Schaurer Oct 13 '20 at 08:50
  • @Sandro Schaurer Yes, it would because "Name" never will be set. – The incredible Jan Aug 22 '22 at 08:28
14

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.

David
  • 208,112
  • 36
  • 198
  • 279
  • 12
    It coule easily be added to the language (theoretically speaking) by inventing a new keyword (just like "value" but the other way around) ... "self" maybe. self = value; – movAX13h Sep 26 '15 at 17:48
  • 1
    A better approach to this problem is tracked here: https://github.com/dotnet/csharplang/issues/133 – Sachin Joseph Apr 14 '18 at 21:13
1

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;
        }
    }
}
computercarguy
  • 2,173
  • 1
  • 13
  • 27