Pasando una propiedad como un parámetro 'out' en C #

81

Supongamos que tengo:

public class Bob
{
    public int Value { get; set; }
}

Quiero pasar el miembro Value como un parámetro de salida como

Int32.TryParse("123", out bob.Value);

pero obtengo un error de compilación, "el argumento 'out' no está clasificado como variable". ¿Hay alguna forma de lograr esto, o voy a tener que extraer una variable, a la:

int value;
Int32.TryParse("123", out value);
bob.Value = value;
thorncp
fuente

Respuestas:

83

Tendría que usar explícitamente un campo y una propiedad "normal" en lugar de una propiedad implementada automáticamente:

public class Bob
{
    private int value;
    public int Value
    { 
        get { return value; } 
        set { this.value = value; }
    }
}

Entonces puede pasar el campo como un parámetro de salida:

Int32.TryParse("123", out bob.value);

Pero, por supuesto, eso solo funcionará dentro de la misma clase, ya que el campo es privado (¡y debería serlo!).

Las propiedades simplemente no te permiten hacer esto. Incluso en VB, donde puede pasar una propiedad por referencia o usarla como un parámetro de salida, básicamente hay una variable temporal adicional.

Si no le importaba el valor de retorno de TryParse, siempre puede escribir su propio método auxiliar:

static int ParseOrDefault(string text)
{
    int tmp;
    int.TryParse(text, out tmp);
    return tmp;
}

Entonces usa:

bob.Value = Int32Helper.ParseOrDefault("123");

De esa manera, puede usar una sola variable temporal incluso si necesita hacer esto en varios lugares.

Jon Skeet
fuente
1
Creo que el problema con el primer enfoque es que si usa el campo directamente (en lugar de la propiedad), es posible que esté pasando por alto las reglas de validación que pueden existir en la propiedad
Andreas Grech
3
@Jon: Creo que le gustaría cambiar int.Parse a int.TryParse en el ejemplo de ParseOrDefault.
shahkalpesh
8
Por cierto, la razón por la que no puede tener una propiedad como parámetro de salida es que establecer una propiedad en realidad es una llamada de función y no una asignación si mira bajo el capó.
Dirk Vollmar
3
Me encantaría ver el azúcar sintáctico adecuado para permitirme pasar una propiedad como parámetro de referencia o de salida. Hagamos el trabajo con el compilador, es más rápido que yo.
Ignacio Soler García
1
@SoMoS: Si es un tipo de valor o no, no importa mi comentario. O un cambio dentro del método al parámetro tiene efecto inmediatamente, o no lo hace. Esto también afecta lo que sucede si se lanza una excepción.
Jon Skeet
7

Puede lograrlo, pero no con una propiedad.

public class Bob {
    public int Value { get; set; } // This is a property

    public int AnotherValue; // This is a field
}

No se puede utilizar outen Value, pero en CAN AnotherValue.

Esto funcionará

Int32.TryParse("123", out bob.AnotherValue);

Pero, las pautas comunes le dicen que no haga público un campo de clase. Por lo tanto, debe utilizar el enfoque de variable temporal.

Pierre-Alain Vigeant
fuente