2010-11-30 6 views
6

En C#, puedo tener una propiedad sin tener que declarar una variable privada. Mi código de VB6 que se parecía a esteobtener; conjunto; sintaxis en C#

'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 

ahora puede tener este aspecto.

public string PhoneNumber{get;set;} 

¿Cómo puedo poner la validación en los métodos getter y setter en C#? Intenté agregar una validación como esta.

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

La parte de este código no se compilará. ¿Debo volver a utilizar una variable privada?

+0

Como dijo Andrew, deberá crear una variable privada para la propiedad. La característica de propiedades automáticas de C# hace esto detrás de escena para usted, pero no puede acceder a esa variable privada de esa manera. tiene que declarar explícitamente que hace algo con él (como validarlo) – Chris

+1

Además, asegúrese de establecer el campo de respaldo en su setter o se ejecutará en una StackOverflowException en tiempo de ejecución. –

+0

No sé si simplemente está simplificando por poner un ejemplo, pero establecer ciegamente una propiedad con un nuevo valor en lugar de arrojar una ArgumentException parece bastante complicado. –

Respuesta

18

Sí, usted tendrá que crear un campo de respaldo:

string _phoneNumber; 

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

Tenga en cuenta que esta aplicación no es diferente de una propiedad en marcha automáticamente. Cuando utiliza una propiedad implementada automáticamente, simplemente le permite al compilador crear el campo de respaldo para usted. Si desea agregar cualquier lógica personalizada al get o set, debe crear el campo usted mismo como lo he mostrado anteriormente.

+0

Gracias. No estaba seguro de si era necesario. – abhi

1

Sí, lo haces. Cuando utiliza la sintaxis de acceso directo "implícita", secretamente crea un campo de respaldo llamado _phoneNumber por usted. Cuando define explícitamente su propiedad, necesita crear su propio campo de respaldo. Justo encima de su propiedad de definición de venta:

private string _phoneNumber; 

y luego en su propiedad acostumbrarse:

get 
{ 
    return _phoneNumber; 
} 
+0

No creo que se llame así, pero tiene un nombre feo largo – CodesInChaos

2

No necesita necesariamente una variable local. Teóricamente, puede implementar cualquier funcionalidad que desee dentro de una propiedad get/set. Pero, en su ejemplo, tiene acceso recursivo a su propiedad get/set lo que no tiene sentido en la forma en que se implementa. Entonces, en su caso concreto, necesitará una variable local, eso es correcto.

2

Haría algo como esto para evitar un NullReferenceException, así como acortar el código general.

public string PhoneNumber 
{ 
    get { return _phoneNumber; } 
    set 
    { 
     var v = value ?? string.Empty; 
     _phoneNumber = v.Length <= 30 ? v : "EXCEEDS LENGTH"; 
    } 
} 
private string _phoneNumber; 
+0

Probablemente sería mejor manejar el valor nulo en su getter, en lugar de su setter. ¿Qué sucede si accede al getter antes de que la propiedad se inicialice? Cambiaría el get a {return _phoneNumber ?? string.Empty; }. Además, debe lanzar una excepción si el valor especificado es demasiado largo, en lugar de reemplazarlo con un valor arbitrario. – Chris

+0

@Chris, si PhoneNumber no puede ser nulo, lo que asume la respuesta de ChaosPandion aquí, entonces tendría que ser capturado en el setter y también en el constructor (los constructores nunca deberían dejar su objeto en un estado inválido). Alternativamente, si podría ser nulo, entonces debería devolver nulo sin verificación (y el cheque se cambió para permitir eso). –

+0

@Chris - Personalmente, creo que la validación que tienen es bastante débil, pero fue algo fuera de tema. Simplemente no soporto el código que es vulnerable a 'NullReferenceException' cuando es tan fácil de resolver. @Jon es absolutamente correcto en su evaluación, aunque probablemente lo llevaría un poco más lejos y usaría un objeto inmutable. – ChaosPandion