C# anonymous backing fields with non-auto properties
Asked Answered
F

5

5

I want to make a private member variable that is private even to the class that owns it, and can ONLY be accessed by its getters and setters. I know you can do this with auto-properties like

private int MyInt{ get; set;}

But I want to be able to modify the getter and setter so (for example) I could log how many times the field has been set (even by the owning class). Something like this

private int MyInt
{
    get{ return hiddenValue; }
    set{ hiddenValue = value; Console.Out.WriteLine("MyInt has been set");}
}

where "hiddenValue" is the member that is only accessible in the getter and setter. Why? because I'm a paranoid defensive programmer, I don't even trust myself :p.

Is this possible in C#? and if so, what is the syntax?

Thanks.

Faruq answered 5/8, 2011 at 3:56 Comment(1)
There are more good reasons than paranoia to strive for this :). It's not unusual with cached properties, i.e. at first access the value is retrieved through databases etc. and stored in a backing field, and for subsequent access the getter uses the backing field instead. And at this point it can be unclear for developers, especially those new to the project, whether to use the property or backing field.Styx
C
6

You really should trust yourself.

And no, you can't make a variable so private even the encapsulating class can't see it.

If you really want this, you could encapsulate the value in a nested class, which would be able to cover its own privates.

class Foo 
{
    class Bar // nested
    {
        private int _value;
        public int Value 
        {
            get { return _value; }
            set { _value = value; /* logic */ }
        }
    }
}

Foo can instantiate a Bar, get at bar.Value, but it cannot get to _value.

Creosol answered 5/8, 2011 at 4:1 Comment(7)
+1 But then again he could use reflection to change the value regardless, still not paranoid enough.Lupercalia
Rats, this would be handy to make code idiot-proof during maintenance. well, nothing is idiot proof, but it'd help. Unfortunately putting it in an encapsulating class adds too much code complexity and chances for mistakes :pFaruq
@Bryan, you know what will ruin your day? Are you ready? Seperate instances of Foos can see each other's privates. Not only can you not hide a member from an instance, you can't hide it from another instance of the same class.Creosol
@Lupercalia yeah, but they'd have to put effort into bypassing accessors. This was more to ensure onChange events get triggered even when the change is caused internally. How do you use reflection on an anonymous backing member? I've been in java-land for the last couple years so I'm just brushing up on my C# again, but I seem to remember needing the member name to modify it through reflection.Faruq
@Bryan, consider that once it's compiled, it's not "anonymous." Auto-implemented properties save you the hassle of defining the backing field, but that doesn't mean there isn't one. You've just offloaded the burden of creating it to the compiler.Creosol
@Anthony Yeah, it is frightening. Makes me afraid that if I'm writing some big system where nodes all interact with eachother, I'm going to forget to call the accessors and my eventing will be all screwed up lol.Faruq
@Anthony... again... Yeah, I know that it isn't anonymous once it gets compiled, but I didn't realize it was named so easily that you could guess it. I figured it was named by some hash value or something. I guess that doesn't stop you from running through a list of all members and screwing with them ALL... but then you're pretty much TRYING to screw up the application, it isn't even an accident at that point :pFaruq
P
4

Is not possible with any language in .Net. And is good. Defensive coding is good, but when becomes paranoid, it makes go crazy other developers who need to maintain it.

Paulitapaulk answered 5/8, 2011 at 4:3 Comment(3)
Defensive programming is needed precisely because other developers need to maintain it!Concave
Still I love it when nicely solutions are being used ( AOP, Code Contracts), but when you start checking the sender and the args for null references and with no intentions to use them later in code, I'm wondering why this paranoia, it's counterproductive.Paulitapaulk
@Mark H... exactly! I always assume that the person working on it after me is a complete idiot. Even if I am that idiot. If I could be guaranteed that the accessors were always called then I'd know for sure that my events would always be fired and that the data was always validated.Faruq
S
3

Aspect-Oriented Programming (AOP) might help, which in a nutshell, allowing you to inject code of your choice before and/or after method calls.

Check out http://code.google.com/p/easyprop/ which is an AOP library specifically designed for watching property changes, and there is examples for working with auto-properties.

NB: I haven't used the library yet, but it looks right up your alley.

Syncopate answered 5/8, 2011 at 4:5 Comment(2)
+1 for mentioning AOP. I think PostSharp is the better framework, though.Formidable
I'm giving PostSharp a look right now. Doesn't quite help with this problem, but it certainly looks helpful in general :pFaruq
U
2

No, this isn't possible in C#.

Your best bet is probably to become less paranoid. :P

Uremia answered 5/8, 2011 at 4:0 Comment(0)
P
1

What you are trying to do, can not be achieved in .NET.

Even the hidden backing field will be visible in IL code. Meaning while you can't see it at design time (in VS) it will be there after the compile.

Pesthole answered 5/8, 2011 at 4:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.