C# Property and Ref Parameter, Why No Sugar

C# property and ref parameter, why no sugar?

Just for info, C# 4.0 will have something like this sugar, but only when calling interop methods - partly due to the sheer propensity of ref in this scenario. I haven't tested it much (in the CTP); we'll have to see how it pans out...

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

you cannot use

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

replace bd.Budget with some variable.

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

Why a property can not be passed as out parameter?

This is valid in VB, but not in C#... VB effectively creates a temporary local variable for you, calls the method passing in the local variable as the argument, and then sets the property with the value of the local variable. C# doesn't usually hide that sort of thing for you.

The method itself needs a variable as the out parameter. It's got to have a storage location it can just write values to. Not a property, not anything it needs to invoke: just a storage location. A property doesn't satisfy that requirement. So there's nothing that can be done by the compiler in the method to allow this.

So either the compiler has to fake it with a temporary variable, as per VB, or disallow it, as per C#. Personally I prefer the C# approach - otherwise it looks as if each time the method assigned a value to the out parameter, the property would be set - which certainly isn't the case.

Why can't I pass indexer as a ref parameter?

An indexer value is not classified as a variable; therefore, you cannot pass an indexer value as a ref or out parameter.

Refer msdn

C#: can 'out' parameters in functions be object properties/variables?

Properties are [a pair of get and set] methods with a cute syntax for invoking them that makes them look like fields.

Out parameters can be references to fields or stack based 'fields' (i.e., locals).

The bridging of this gap is generally not addressed by languages (and definitely not directly by the CLR and IL model). (+1 on @Heinzi for the VB trickery references)

Why is the `ref` keyword not mandatory here?

ref is ment to be used when you change the reference, not the referenced instance. So you can modify the referenced instance without using ref, however when you want to reference another object, you have to use ref

Having said this Fill will just modify what was passed to it, it won´t create a new DataTable.

On the other hand when you want to return another instance, you have to use ref:

void DoSomething(ref dt)
{
dt = new DataTable();
// do something with the new table
}

Now you have two tables, one that was passed to DoSomething and a second one that was created within that method and that doesn´t have anything in common with the former. However the calling code references that new instance now, the original reference is lost.

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

use variable, but not property

var obj = Globals.NameList;
Array.Resize(ref obj , 0);
Globals.NameList=obj;

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

Of course it won't work, because you are updating the local variable v and discarding it after the setter is executed.

You either have to check manually and then rise the property changed event yourself, or you assign v to _wcfObject.SomeProperty afterwards.

public string SomeProperty
{
get { return _wcfObject.SomeProperty; }
set {
var v = _wcfObject.SomeProperty;
Set(nameof(SomeProperty), ref v, value);
_wcfObject.SomeProperty = v;
}
}

That just looks pretty... "odd". Best may be to use proper backing fields, it's bad practice anyways to directly operate on models when wrapping them around, as you can't discard the changes.

private string someField;
public string SomeProperty
{
get { return someField; }
set {
Set(nameof(SomeProperty), ref someField, value);
}
}

public ICommand DoSomethingCommand
{
return new DelegateCommand(DoSomething);
}

private void DoSomething()
{
// apply your ViewModel state to the _wcfObject and do something with it
}

Then your _wcfObject is unaffected by the changes user do, until he initiates an action/command.

Enhancing C# syntactic sugar (or getting around Cannot use ref or out parameter)

In isolation, a way better way to write this code would be:

public ResultInfo DoSqlAction(Func<bool> f, string task, string ctx) {
try {
if (f.Invoke()) {
return new ResultInfo(seq, task, "Success", ctx, true);
} else {
return new ResultInfo(seq, task, "Fail", ctx, false);
}
} catch (Exception ex) {
return new ResultInfo(seq, task, "Error: " + ex.Message, ctx, false);
}
}

And on the outside:

while (/* there's stuff to do */) {
var result = DoSqlAction(/* the next stuff */);
infos.Add(result);
if (!result.Succeeded)
break;
}

or the equivalent. This eliminates the odd side-effectful function, the ref parameter, etc. And it's shorter.



Related Topics



Leave a reply



Submit