Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm getting the above error and unable to resolve it. I googled a bit but can't get rid of it.

Scenario:

I have class BudgetAllocate whose property is budget which is of double type.

In my dataAccessLayer,

In one of my classes I am trying to do this:

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

Which is throwing this error:

Property or indexer may not be passed as an out or ref parameter at compile time.

I even tried this:

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

Everything else is working fine and references between layers are present.

like image 942
Pratik Avatar asked Dec 23 '10 13:12

Pratik


2 Answers

Others have given you the solution, but as to why this is necessary: a property is just syntactic sugar for a method.

For example, when you declare a property called Name with a getter and setter, under the hood the compiler actually generates methods called get_Name() and set_Name(value). Then, when you read from and write to this property, the compiler translates these operations into calls to those generated methods.

When you consider this, it becomes obvious why you can't pass a property as an output parameter - you would actually be passing a reference to a method, rather than a reference to an object a variable, which is what an output parameter expects.

A similar case exists for indexers.

like image 144
Mike Chamberlain Avatar answered Oct 08 '22 21:10

Mike Chamberlain


This is a case of a leaky abstraction. A property is actually a method, the get and set accessors for an indexer get compiled to get_Index() and set_Index methods. The compiler does a terrific job hiding that fact, it automatically translates an assignment to a property to the corresponding set_Xxx() method for example.

But this goes belly up when you pass a method parameter by reference. That requires the JIT compiler to pass a pointer to the memory location of the passed argument. Problem is, there isn't one, assigning the value of a property requires calling the setter method. The called method cannot tell the difference between a passed variable vs a passed property and can thus not know whether a method call is required.

Notable is that this actually works in VB.NET. For example:

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 

The VB.NET compiler solves this by automatically generating this code for the Run method, expressed in C#:

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

Which is the workaround you can use as well. Not quite sure why the C# team didn't use the same approach. Possibly because they didn't want to hide the potentially expensive getter and setter calls. Or the completely undiagnosable behavior you'll get when the setter has side-effects that change the property value, they'll disappear after the assignment. Classic difference between C# and VB.NET, C# is "no surprises", VB.NET is "make it work if you can".

like image 41
Hans Passant Avatar answered Oct 08 '22 20:10

Hans Passant