Una propiedad o indexador no se puede pasar como un parámetro de salida o ref

Recibo el error anterior y no puedo resolverlo. Busqué en Google un poco, pero no puedo deshacerme de él.

Guión:

Tengo una clase BudgetAllocate cuya propiedad es un presupuesto que es de tipo doble.

En mi dataAccessLayer,

En una de mis clases estoy tratando de hacer esto:

double.TryParse(objReader[i].ToString(), out bd.Budget); 

Que está arrojando este error:

La propiedad o el indizador no se pueden pasar como un parámetro de salida o ref en el tiempo de comstackción.

Incluso intenté esto:

 double.TryParse(objReader[i].ToString().Equals(DBNull.Value) ? "" : objReader[i].ToString(), out bd.Budget); 

Todo lo demás funciona bien y las referencias entre capas están presentes.

no puede utilizar

 double.TryParse(objReader[i].ToString(), out bd.Budget); 

reemplace bd.Budget con alguna variable.

 double k; double.TryParse(objReader[i].ToString(), out k); 

Otros le han dado la solución, pero en cuanto a por qué esto es necesario: una propiedad es solo azúcar sintáctica para un método .

Por ejemplo, cuando declaras una propiedad llamada Name con un getter y un setter, bajo el capó el comstackdor realmente genera métodos llamados get_Name() y set_Name(value) . Luego, cuando lee y escribe en esta propiedad, el comstackdor traduce estas operaciones en llamadas a esos métodos generados.

Cuando considera esto, resulta obvio por qué no puede pasar una propiedad como parámetro de salida; en realidad, estaría pasando una referencia a un método , en lugar de una referencia a un objeto como variable , que es lo que espera un parámetro de salida.

Un caso similar existe para los indexadores.

Este es un caso de abstracción con fugas. Una propiedad es en realidad un método, los accesadores get y set para un indexador se comstackn en los métodos get_Index () y set_Index. El comstackdor hace un excelente trabajo ocultando ese hecho, traduce automáticamente una asignación a una propiedad al método set_Xxx () correspondiente, por ejemplo.

Pero esto se agota cuando pasa un parámetro de método por referencia. Eso requiere que el comstackdor JIT pase un puntero a la ubicación de la memoria del argumento pasado. El problema es que no hay uno, asignar el valor de una propiedad requiere llamar al método setter. El método llamado no puede diferenciar entre una variable pasada frente a una propiedad pasada y, por lo tanto, no puede saber si se requiere una llamada al método.

Notable es que esto realmente funciona en VB.NET. Por ejemplo:

 Class Example Public Property Prop As Integer Public Sub Test(ByRef arg As Integer) arg = 42 End Sub Public Sub Run() Test(Prop) '' No problem End Sub End Class 

El comstackdor de VB.NET resuelve esto generando automáticamente este código para el método Run, expresado en C #:

 int temp = Prop; Test(ref temp); Prop = temp; 

Cuál es la solución alternativa que puede usar también. No estoy seguro de por qué el equipo de C # no utilizó el mismo enfoque. Posiblemente porque no querían esconder las llamadas de getter y setter potencialmente costosas. O el comportamiento completamente no diagnosticable que obtendrás cuando el colocador tenga efectos secundarios que cambien el valor de la propiedad, desaparecerán después de la asignación. La diferencia clásica entre C # y VB.NET, C # es “sin sorpresas”, VB.NET es “haz que funcione si puedes”.

Coloque el parámetro out en una variable local y luego establezca la variable en bd.Budget . bd.Budget :

 double tempVar = 0.0; if (double.TryParse(objReader[i].ToString(), out tempVar)) { bd.Budget = tempVar; } 

Actualización : Directamente desde MSDN:

Las propiedades no son variables y, por lo tanto, no pueden pasarse como parámetros.

http://msdn.microsoft.com/en-us/library/t3c3bfhx(v=vs.80).aspx

Posiblemente de interés, podrías escribir el tuyo:

  //double.TryParse(, out bd.Budget); bool result = TryParse(s, value => bd.Budget = value); } public bool TryParse(string s, Action setValue) { double value; var result = double.TryParse(s, out value); if (result) setValue(value); return result; } 

Entonces, el presupuesto es una propiedad, ¿correcto?

Primero, configúrelo en una variable local y luego establezca el valor de la propiedad en ese.

 double t = 0; double.TryParse(objReader[i].ToString(), out t); bd.Budget = t;