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
Update Requires a Valid Updatecommand When Passed Datarow Collection with Modified Rows
Get List<> Element Position in C# Using Linq
How to Get Full Host Name + Port Number in Application_Start of Global.Aspx
Get the Application Pool Identity Programmatically
What Does the Tilde Mean in an Expression
How to Fill Dataset with Multiple Tables
How to Use C# 8 with Visual Studio 2017
The Remote Server Returned an Unexpected Response: (413) Request Entity Too Large
Regex That Matches a Newline (\N) in C#
Why Does the Async Keyword Exist
Opening a "Known File Type" into Running Instance of Custom App - .Net
Use Linq to Generate Direct Update Without Select
C# - Inconsistent Math Operation Result on 32-Bit and 64-Bit