Reputation: 32710
I'm aware of 3 parameter evaluation types in C#:
My professor stated that C# also supports by-result, which he explained as:
- Argument has to be LHS-compatible
- Create local copy of argument and operate on that
- After successful processing of method body, write value of copy back to the parameter source
I don't see how this refers to any of the above types.
Upvotes: 2
Views: 398
Reputation: 9587
I think your professor might be referring to plain variable reassignment upon method completion (i.e. i = DoSomething(i)
), or possibly operators which result in variable reassignment under the covers, i.e. ++
.
To illustrate this:
class Immutable
{
public readonly int Value;
public Immutable(int value)
{
this.Value = value;
}
public static Immutable operator ++(Immutable obj)
{
return new Immutable(obj.Value + 1);
}
}
Now we can do the following:
Immutable a = new Immutable(1);
Immutable originalA = a;
Debug.Assert(a.Value == 1);
Debug.Assert(a == originalA); // Same instance (obviously).
a++;
Debug.Assert(a.Value == 2);
Debug.Assert(a != originalA); // New instance.
This appears to satisfy all criteria:
Immutable
.obj
inside the body of the method, it won't affect the original location).a
is reassigned once the operator has finished executing, and will point to the newly-created instance.EDIT
While this is definitely not the answer as it does not satisfy any of the points, I think it's worth mentioning that you can also get the "by ref" semantics by passing around pointers, which I am sure everyone knows. What some may not know, however, is that this can also be done using TypedReference
, which is a special beast in MS C#:
void DodgyIncrement()
{
int i = 0;
this.Increment(__makeref(i));
Debug.Assert(i == 1);
}
void Increment(TypedReference i)
{
__refvalue(i, int) += 1;
}
Upvotes: 0
Reputation: 942109
No, not an explicit C# language feature. It does not suffer from major aliasing problems, the kind that are common when a language only supports pass-by-reference or has pointers as a first-order language feature. And very little syntax to make threading easier, beyond the lock keyword.
One rule in C# that helps is that it forbids passing a property by reference, a problem that can only be solved by call-by-result. Notable is that VB.NET doesn't have this rule and solves it by implementing call-by-result automatically. This does have a knack for causing surprises.
It does occur in practice on a MarshalByRefObject that lives in another execution context. Like another AppDomain or another machine. Necessarily so, a ref argument needs to be copied across the context boundary before the call and copied back afterwards. This is however largely transparent to the program, not counting a quirk that requires applying the [Out] attribute explicitly.
Upvotes: 2
Reputation: 100555
While it is not clear what teacher meant, it is possible to get code that textually match something like
int i = 1; f(i); //now i is 2
by using lambda expression that captures local variable.
int i = 1;
Action<int> f = v => i = 2 * v;
f(i);
Console.WriteLine(i); // now i is 2
Note that i
in call to f
is passed strictly "by value". It could be as well f(42)
- parameter does not have any impact on what variable will be changed as result of execution.
Upvotes: 2