8

In C#, I can have a property without having the need to declare a private variable. My VB6 code that looked like this

'local variable(s) to hold property value(s)
Private mvarPhoneNumber As String 'local copy
Public Property Let PhoneNumber(ByVal vData As String)
'used when assigning a value to the property, on the left side of an assignment.
'Syntax: X.PhoneNumber = 5
    mvarPhoneNumber = vData
End Property


Public Property Get PhoneNumber() As String
'used when retrieving value of a property, on the right side of an assignment.
'Syntax: Debug.Print X.PhoneNumber
    PhoneNumber = mvarPhoneNumber
End Property

can now look like this.

public string PhoneNumber{get;set;}

How can I put validation in the getter and setter methods in C#? I tried adding a validation like this.

public string PhoneNumber
        {
            get
            {
                return PhoneNumber;
            }
            set
            {
                if (value.Length <= 30)
                {
                    PhoneNumber = value;
                }
                else
                {
                    PhoneNumber = "EXCEEDS LENGTH";
                }
            }
        }

The get part of this code won't compile. Do I need to revert to using a private variable?

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
abhi
  • 3,082
  • 6
  • 47
  • 73
  • As Andrew said, you will need to create a private variable for the property. The automatic properties feature of C# actually does this behind the scenes for you, but you can't access that private variable that way. you have to explicitly declare it to do anything with it (such as validate it) – Chris Nov 30 '10 at 20:37
  • 1
    Also, make sure you set the backing field in your setter or you will run into a StackOverflowException at runtime. – Mark Avenius Nov 30 '10 at 20:39
  • I don't know if you are just simplifying for the sake of example, but blindly setting a property to a new value rather than throwing an ArgumentException seems pretty fraught. – Jon Hanna Nov 30 '10 at 23:59
  • 1
    I'm going to go slightly off topic and respond to your introductory remarks. The VB6 equivalent to the C# auto-property `public string PhoneNumber{get;set;}` is actually a simple public field, `Public PhoneNumber As String`. In VB6 you can swap public fields to properties at will without affecting any functionality: callers don't need to be recompiled, data binding still works... It's one area where VB6 was better than .Net. – MarkJ Dec 01 '10 at 10:29

5 Answers5

18

Yes, you will have to create a backing field:

string _phoneNumber;

public string PhoneNumber
{
    get
    {
        return _phoneNumber;
    }
    set
    {
        if (value.Length <= 30)
        {
            _phoneNumber = value;
        }
        else 
        {
            _phoneNumber = "EXCEEDS LENGTH";
        }
    }
}

Keep in mind that this implementation is no different from an automatically implemented property. When you use an automatically implemented property you are simply allowing the compiler to create the backing field for you. If you want to add any custom logic to the get or set you have to create the field yourself as I have shown above.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
2

You do not necessarily need a local variable. Theoretically, you could implement whatever functionality you want within a get/set property. But, in your example, you have a recursive access of your get/set property what makes no sense in the way it is implemented. So, in your concrete case, you will need a local variable, that's right.

Flinsch
  • 4,296
  • 1
  • 20
  • 29
2

I would do something like this as to avoid a NullReferenceException as well as shorten the overall code.

public string PhoneNumber
{
    get { return _phoneNumber; }
    set 
    {
        var v = value ?? string.Empty; 
        _phoneNumber = v.Length <= 30 ? v : "EXCEEDS LENGTH"; 
    }
}
private string _phoneNumber;
ChaosPandion
  • 77,506
  • 18
  • 119
  • 157
  • Would probably be better to handle the null value in your getter, rather than your setter. What if you access the getter before the property is ever initialized? I'd change the get to { return _phoneNumber ?? string.Empty; }. Also, you should throw an exception if the value specified is too long, rather than replacing it with an arbitrary value. – Chris Nov 30 '10 at 21:41
  • @Chris, if PhoneNumber can't be null - which ChaosPandion's answer here assumes - then it would have to be caught in the setter and also in the constructor (constructors should never leave their object in an invalid state). Alternatively, if it could be null, then it should just return null with no check (and the check changed to allow that). – Jon Hanna Nov 30 '10 at 23:57
  • @Chris - Personally I think the validation they have is rather weak but it was kind of off topic. I just can't stand code that is vulnerable to `NullReferenceException` when it is so easy to resolve. @Jon is absolutely correct in his assessment although I would probably take it a bit further and use an immutable object. – ChaosPandion Dec 01 '10 at 00:23
  • If you're going to make absolutely sure you initialize the private variable to a non-null value and absolutely cannot have a null value stored in the private variable, then sure, prevent it in the setter. It's been my general experience though that what we're talking about is ensuring that any external class that references the property doesn't get a null reference exception, in which case handling it in the getter is much cleaner and less verbose. – Chris Dec 01 '10 at 19:30
1

Yes you do. When you use the shortcut "implicit" syntax, it secretly creates a backing field called _phoneNumber for you. When you explicitly define your property, you need to make your own backing field. Right above your property definition put:

private string _phoneNumber;

and then in your property get use:

get
{
    return _phoneNumber;
}
Patrick Karcher
  • 22,995
  • 5
  • 52
  • 66
1

Look here for several many alternatives: Acessing the backing field in an auto property

But the short answer is Yes, you will have to have backing field for validations.

Community
  • 1
  • 1
Madhur Ahuja
  • 22,211
  • 14
  • 71
  • 124