views:

947

answers:

7

Is there any way to access the backing field for a property in order to do validation, change tracking etc.?

Is something like the following possible? If not is there any plans to have it in .NET 4 / C# 4?

public string Name
{
    get;
    set
    {
        if (value != <Keyword>)
        {
            RaiseEvent();
        }
        <Keyword> = value;
    }
}

The main issue I have is that using auto properties doesn't allow for the same flexibility in validation etc. that a property with a explicit backing field does. However an explicit backing field has the disadvantage in some situations of allowing the class it is contained in to access the backing field when it should be accessing and reusing the validation, change tracking etc. of the property just like any other class that may be accessing the property externally.

In the example above access to the backing field would be scoped to the property thus preventing circumvention of the property validation, change tracking etc.

Edit: I've changed < Backing Field > to < Keyword >. I would propose a new keyword similar to value. field would do nicely although I'm sure it's being used in a lot of existing code.

+1  A: 

If you're gonna do so, why you are using auto properties?!

A simple property has done it way back in 1.0. I don't think it makes sense to add complexity to the language for every special case. You either need the property to do plain store/retrieve model or need more than that. In the latter case, a normal property will do.

Mehrdad Afshari
The benefit of auto properties is that you are forced to use the property rather than the backing field from methods within the class.
Jonathan Parker
I don't see any benefit in forcing a class not to use what it declares. This is why we don't have less than `private` access modifiers.
Mehrdad Afshari
I know but in some cases the field is merely storage. There's no other reason to declare it and you want to be able to control how that storage is accessed no matter where it is.
Jonathan Parker
Then you'd need to ask yourself: Do I really need to have this control for my *own* class. If you don't, keep it simple. If you do, your class is probably larger than it should be and should be split up.
Mehrdad Afshari
Yes that's a good point, I guess I'm just after more clean, succinct and elegant code.
Jonathan Parker
I think it's about enforcing encapsulation too.
Jonathan Parker
Encapsulation does not include a class hiding its state from itself.
Greg D
+6  A: 

No there isn't. If you want to access the backing field, then don't use auto properties and roll your own.

I agree that it would be great to have a field that was only accessible by the property and not by the rest of the class. I would use that all the time.

Ray
I would like to enforce use of the property from within the class that the property is in. I don't want code in the class to access the field directly.
Jonathan Parker
Classes must be able to trust themselves to properly handle their own privates.
Greg D
IMO this is the answer to the *actual* question. The response marked as the answer is an answer to a separate tangential question : /
Catskul
+1  A: 

You can't do this I'm afraid. That's one of the reasons I started writing MoXAML Power Toys, to provide the ability to convert automatic properties into Notify properties.

Pete OHanlon
Looks interesting. Still doesn't solve the problem of having a field lying around which should not be accessible except from within the scope of the property.
Jonathan Parker
+2  A: 

As the MSDN states:

"In C# 3.0 and later, auto-implemented properties make property-declaration more concise when no additional logic is required in the property accessors. They also enable client code to create objects When you declare a property as shown in the following example, the compiler creates a private, anonymous backing field can only be accessed through the property's get and set accessors."

Since you have additional logic in you accessors, the use of auto-implemented properties is not appropriate in your scenario.

While the backing field does exist, it is given a mangled name to stop you referencing it easily - the idea is that you never reference the field directly. For interests sake, you can use Reflector to disassemble your code and discover the field name, but I would recommend you not use the field directly as this name may indeed be volatile, so your code could break at any time.

Daniel Paull
I was under the impression that they only reason for the mangled name was to make sure it was unique. Not sure how it does that though. It adds in weird characters that aren't valid for a variable name.
Jonathan Parker
What I don't understand is why the anonymous field even needs a name...
Daniel Paull
+3  A: 

Having read your comments in Mehrdad's answer, I think I understand your problem a bit better.

It appears that you are concerned about the ability of the developer to access private state in the class they are writing, bypassing your validation logic, etc. This suggests that the state should not be contained in the class at all.

I would suggest the following strategy. Write a generic class that represents a ValidatedValue. This class holds only the backing value and only allows access/mutation via get and set methods. A delegate is passed to the ValidatedValue to represent the validation logic:

public class ValidatedValue< T >
{
    private T m_val;
    public ValidationFn m_validationFn;

    public delegate bool ValidationFn( T fn );

    public ValidatedValue( ValidationFn validationFn )
    {
        m_validationFn = validationFn;
    }

    public T get()
    {
        return m_val;
    }

    public void set(T v)
    {
        if (m_validationFn(v))
        {
            m_val = v;
        }
    }
}

You could, of course, add more delegates as required (eg, to support pre/post change notification).

Your class would now use the ValidatedValue in place of a backing store for your property.

The example below shows a class, MyClass, with an integer that is validated to be less than 100. Note that the logic to throw an exception is in MyClass, not the ValidatedValue. This allows you to do complex validation rules that depend on other state contained in MyClass. Lambda notation was used to construct the validation delegate - you could have bound to a member function instead.

public partial class MyClass
{
    private ValidatedValue<int> m_foo;

    public MyClass()
    {
        m_foo = new ValidatedValue<int>(
            v => 
            {
                if (v >= 100) RaiseError();
                return true;
            }
        );
    }

    private void RaiseError()
    {
        // Put your logic here....
        throw new NotImplementedException();
    }

    public int Foo
    {
        get { return m_foo.get(); }
        set { m_foo.set(value); }
    }
}

Hope that helps - somewhat off the original topic, but I think it's more inline with your actual concerns. What we have done is taken the validation logic away from the property and put it on the data, which is exactly where you wanted it.

Daniel Paull
It's a nice solution but a lot of code where accessing the field in the same way we access the new value in a setter with the value keyword would be much more succinct and elegant.
Jonathan Parker
You can probably make the syntax nicer by adding operator= and coersion to T on the ValidatedValue class. Basically you want it to behave like a ValidatedValue<T> is a T.
Daniel Paull
A: 

Using reflection, I'm sure you can figure out the exact name and manipulate it; sounds like a lot of work. If you're going to write a bunch of code, I like Daniel Paull's solution better.

Another approach is to make your own "hidden" field using a simple convention together with a couple of attributes to hide your hidden field a bit from Visual Studio:

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[DebuggerDisplay("")]
private string _ForPropertyONLY_Name;
public string Name
{
   get { return _ForPropertyONLY_Name; }
   set
   {
      if (value != _ForPropertyONLY_Name)
      {
         RaiseEvent();
      }
      _ForPropertyONLY_Name = value;
   }
}

It's not completely foolproof, but perhaps good enough? There might even be a way to write a Code Analysis (FxCop) rule to enforce this naming convention.

Dan
A: 

No, but you can in a subclass:

public class Base
{
    public string Name
    {
        get;
        virtual set;
    }
}

public class Subclass : Base
{
    // FIXME Unsure as to the exact syntax.
    public string Name
    {
        override set
        {
            if (value != base.Name)
            {
                RaiseEvent();
            }

            base.Name = value;
        }
    }
}
strager