A property or indexer may not be passed as an out or ref parameter

Hoy, mi compañero de trabajo y yo estabamos dándole vueltas al por qué de este error en el compilador de C# y no en el de VB.NET. Mirando una buena explicación del por qué el compilador de C# no permite esto, he encontrado esta:

a.cs

class zzz
{
    public static void Main()
    {
        yyy a = new yyy();
        a.aa = 10;
        a.abc(ref a.aa);
    }
}
 
class yyy
{
    public int aa
    {
        get { return 0; }
        set { }
    }
 
    public void abc(ref int b)
    {
 
    }
} 

Compiler Error

a.cs(7,11): error CS0206: A property or indexer may not be passed as an out or ref parameter

If it walks like a duck, quacks like a duck, it's a duck. A property looks and feels like a variable but it is actually a series of functions or to be technically correct, accessors. Only a storage or memory location can be passed as a ref or an out parameter. A property is not allocated any memory and thus cannot be used wherever a variable can be used. All the restrictions of static  apply to static properties too. The get accessor must terminate either in a return or a throw statement. Control cannot flow off the accessor body at the end. A set accessor is like a function that returns void and it has an implicit parameter value.

fuente original: http://www.vijaymukhi.com/documents/books/csadv/chap1.htm

Pero me picaba la curiosidad y he querido ver como lo trata el compilador de VB.NET (Que era la solución que pensabamos para C#):

Module Module1
    Sub Main()
        Dim a As New yyy()
        a.aa = 10
        yyy.abc(a.aa)
    End Sub
End Module
 
Class yyy
    Private _codigo As Integer
    Public Property aa() As Integer
        Get
            Return 0
        End Get
 
        Set(ByVal value As Integer)
            _codigo = value
        End Set
    End Property
 
    Public Shared Sub abc(ByRef b As Integer)
 
    End Sub
End Class

Visto con Reflector:

[STAThread]
public static void Main()
{
    yyy a = new yyy();
    a.aa = 10;
    yyy VB$t_ref$S0 = a;
    int VB$t_i4$S0 = VB$t_ref$S0.aa;
    yyy.abc(ref VB$t_i4$S0);
    VB$t_ref$S0.aa = VB$t_i4$S0;
}
 

Lo hace con una variable auxiliar del tipo de la propiedad :)

Cuanto menos curioso, ¿No?

Salu2

Published 4/4/2008 14:01 por Luis Ruiz Pavón
Archivado en: ,,,,
Comparte este post:
http://geeks.ms/blogs/lruiz/archive/2008/04/04/a-property-or-indexer-may-not-be-passed-as-an-out-or-ref-parameter.aspx

Comentarios

# re: A property or indexer may not be passed as an out or ref parameter

¡Excelente post, Luis!

No sabía que VB sí lo permitiera.

Creo que esta diferencia "apunta" al distinto nivel al que intentan orientarse los lenguajes. Los creadores de C# quisieron que el programador fuera consciente de que una propiedad *no es* un l-value ("left hand value", en la jerga de C), mientras que los de VB prefirieron ocultar ese hecho.

Por cierto, a primera vista no me queda claro por qué los de VB generan una variable temporal para 'a' también, cuando solo haría falta una para 'aa', ¿no?

Salu2 - Octavio

Friday, April 04, 2008 3:56 PM por Octavio Hernández

# re: A property or indexer may not be passed as an out or ref parameter

Gracias por el comentario Octavio.

La verdad es que tienes toda la razón , no me había fijado :)

Salu2

Sunday, April 06, 2008 11:58 PM por Luis Ruiz Pavón