C# - ref this (reference to self) - c#

Suppose I have a code in C++:
class A {
int x = 20;
void Interact(A* Other) {
if (x % 2 == 0) { Other->x++; x /= 2; } //some advanced operation
}
public:
void MakeInteraction(A* Other) {
Interact(Other);
Other->Interact(this);
}
};
int main() {
A a, b;
a.MakeInteraction(&b);
}
Problem is, if I want to make something similar in C#, I meet the barrier - of course I don't need to use pointers, but I can't use reference to this object:
class A
{
int x = 20;
void Interact(ref A Other)
{
if (x % 2 == 0) { Other.x++; x /= 2; }
}
public void MakeInteraction(ref A Other)
{
Interact(ref Other); //works
Other.Interact(ref this); //doesn't work
Other.Interact(this); //still doesn't work
A a = this;
Other.Interact(ref a);
this = a; //REALLY? THIS DOESN'T WORK TOO?!
}
}
I'm angry because I thought that C# corrects flaws of C++ and leaves as much options as originally C++, minus pointers. Now seems that switching from C++ to C# requires to change a way of thinking... again.

You don't need to use ref in your parameter declarations. For reference types like your class A, a parameter declared as just A other will cause C# to pass a reference to the object.
A parameter declared as A other in C# is similar to A* other in C++.
A parameter declared as ref A other in C# is similar to A** other in C++.
class A
{
int x = 20;
void Interact(A other)
{
if (x % 2 == 0) { other.x++; x /= 2; }
}
public void MakeInteraction(A other)
{
Interact(other);
other.Interact(this);
}
static void Main()
{
A a = new A();
A b = new A();
a.MakeInteraction(b);
}
}

Related

Unsafe structs in C#

I wanted to try c#'s unsafe 'feature' by creating simple structs (Vector, Particle).
SITUATION
I have this 2 structs and want to inject position and velocity vectors into my Particle struct.
As a test I wanted to print out position's X value, but somehow I'm getting random values.
I have the following code here
Vector
public readonly struct Vector
{
public int X { get; }
public int Y { get; }
public Vector(int x, int y)
{
X = x;
Y = y;
}
}
Particle
public unsafe struct Particle
{
private Vector* mPosition;
private Vector* mVelocity;
public Particle(Vector position, Vector velocity = default)
{
mPosition = &position; // here is x 10
mVelocity = &velocity;
}
public int GetPosX()
{
return mPosition->X; // but here not
}
}
Program
public class Program
{
private static void Main(string[] args)
{
var pos = new Vector(10, 5);
var obj = new Particle(pos);
Console.WriteLine(obj.GetPosX()); // prints random value
}
}
PROBLEM
It prints a random value instead of 10.
class Program {
static void Main (string [ ] args) {
unsafe {
Vector pos = new Vector(10, 5);
Particle obj = new Particle(&pos);
// &pos is at position 0xabcdef00 here.
// obj.mPosition has a different value here. It points to a different address? Or am I misunderstanding something
Console.WriteLine(obj.GetPosX( ));
}
}
}
public struct Vector {
public int X;
public int Y;
public Vector (int x, int y) {
X = x;
Y = y;
}
}
public unsafe struct Particle {
private Vector* mPosition;
public Particle (Vector *position) {
mPosition = position; // here is x 10
}
public int GetPosX ( ) {
return mPosition->X; // still 10 here
}
}
This works for me.
Please ... do not ask me why it does. You will notice that I didn't change that much. Just calling Particle with *pos instead of pos. For some reason that fixes the problem. You have to wrap the code with unsafe then and change the constructor for Particle obviously.
I could speculate about why it works, but I'd rather not. Maybe the pointer changes when you pass pos as a parameter for some reason?
You could not take the ref with right value.
Create a variable like int posX = 10;
And you can take the reference with variable. You take the compile time reference and read the runtime reference.
Don't use pointers without fixed. C# stack performance ise very good. You dont need this.
Usually pointers use with linking (C/Cpp dynamic library linking etc). If you have large structs (30 bytes and greater) then you can use the ref parameter tag.

Assigning to a variable by reference?

Thanks to the kind folks who answered my previous question from a few days ago, I now know how to pass arguments by reference:
static void Main()
{
int i = 0;
Add(ref i, 100);
// now i == 100
}
static void Add(ref int arg, int increment)
{
arg += increment;
}
But is there a way for me not to just pass i by reference, but actually store its location in another variable? By that I mean use i like I did in my example; affecting the original instance, but in a way that's permanently linked and not leaving scope.
I vaguely know that I could use a pointer to determine the location in unsafe context but I was wondering if I could do this without any of that, or if it is just recommended to use the unsafe method.
If you are using C# 7 you can use ref local and ref return to store an updateable reference to any field.
In this example I change the private field _privateField from 0 to 100 from outside Foo, the class in which it is defined, by returning it as a ref int and updating it by reference.
class Foo
{
private int _privateField = 0;
public ref int GetReference()
{
return ref _privateField;
}
public override string ToString()
{
return _privateField.ToString();
}
}
public class Program
{
public static void Main()
{
var foo = new Foo();
var referenceToPrivateField = foo.GetReference();
referenceToPrivateField = 100;
Console.WriteLine(foo);
}
}
Prior to that, you'd have to store the value in a field contained in an object, and pass around a reference to the object instead.
In this example I change the value from 0 to 100 from outside Foo, even though it is stored (indirectly) in a field that is private inside the Foo instance.
class ValueTypeReference<T> where T : struct
{
public T Value { get; set; }
}
class Foo
{
private ValueTypeReference<int> _privateField = new ValueTypeReference<int>{ Value = 0 };
public ValueTypeReference<int> GetReference()
{
return _privateField;
}
public override string ToString()
{
return _privateField.Value.ToString();
}
}
public class Program
{
public static void Main()
{
var foo = new Foo();
var referenceToPrivateField = foo.GetReference();
referenceToPrivateField.Value = 100;
Console.WriteLine(foo);
}
}
Output:
100
Well, if I udnerstood you correctly, you want the variable to have global scope, which can be achieved by putting variable as class field/property:
class Program
{
private static int _i;
static void Main()
{
_i = 0;
Add(100);
// now _i == 100
}
static void Add(int increment)
{
_i += 100;
}
}

Are value type variables declared in local function stack-allocated?

I was reading about local functions introduced recently and started to wonder about the question. Afaik local variables of value types in lambdas are allocated in the heap. Also there was something that local function have advantage over lambdas when capturing value types, which do not require in this case additional heap allocation. Still following is not clear to me:
Are local value type variables declared in local functions allocated on stack?
What about value type variables, that are declared in "parent" function and captured in local function?
(provided that parent is not anonymous itself).
edit:
int ParentFunction ()
{
int parentVarLambda = 0;
int parentVarLocal = 0;
Func<int> lamdaFuncion = () => parentVarLambda + 1;
int a = lamdaFuncion();
int b = LocalFunction();
return a + b;
int LocalFunction()
{
int localFuncVar = 1;
return parentVarLocal += localFuncVar ;
}
}
where will be parentVarLambda, parentVarLocal and localFuncVar allocated?
None of it is heap-allocated, unless something else is going on (particularly if the compiler can't guarantee that the lifetime of variables captured by the local function don't exceed the lifetime of the parent method, e.g. if a delegate refers to the local function, or the local function contains yield return or await statements).
Let's say you have:
public void M(int i) {
Inner(i + 1);
void Inner(int x)
{
int j = x + i;
Console.WriteLine(j);
}
}
Using the wonderful SharpLab, we can see this gets compiled to:
[StructLayout(LayoutKind.Auto)]
[CompilerGenerated]
private struct <>c__DisplayClass0_0
{
public int i;
}
public void M(int i)
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = default(<>c__DisplayClass0_0);
<>c__DisplayClass0_.i = i;
<M>g__Inner|0_0(<>c__DisplayClass0_.i + 1, ref <>c__DisplayClass0_);
}
[CompilerGenerated]
internal static void <M>g__Inner|0_0(int x, ref <>c__DisplayClass0_0 P_1)
{
Console.WriteLine(x + P_1.i);
}
So the compiler's taken our inner function, and rewritten it as a static method. Parameters to the inner function remain as parameters to the static method. Things captured by the inner function end up as fields on a compiler-generated struct, which is passed by ref (to avoid copying, and so that changes made to it in the static method are reflected in the calling method).
Structs allocated in that inner function will just be allocated the same in the static method - i.e. on the stack.
Now let's compare that to equivalent code, but using a delegate:
public void M(int i) {
Action<int> inner = x =>
{
int j = x + i;
Console.WriteLine(j);
};
inner(i + 1);
}
This gets compiled to:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public int i;
internal void <M>b__0(int x)
{
Console.WriteLine(x + i);
}
}
public void M(int i)
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.i = i;
new Action<int>(<>c__DisplayClass0_.<M>b__0)(<>c__DisplayClass0_.i + 1);
}
Here we can see the difference. The compiler's generated a new class, which has fields to hold the variables captured by the delegate, and has a method on it which contains the body of our delegate. It's had to use a class, rather than a struct passed by reference.
To understand why, think about the fact that your code can pass a delegate around - it could store it in a field, or return it, or pass it to another method. In that case, it's not just being synchronously called by its parent (as a local function must be), but it has to instead carry around the variables it captured with it.
Note that something similar happens if we create a delegate referring to a local function:
public void M(int i) {
void Inner(int x)
{
int j = x + i;
Console.WriteLine(j);
}
Action<int> inner = Inner;
inner(i + 1);
}
This gets compiled to the same as before:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public int i;
internal void <M>g__Inner|0(int x)
{
Console.WriteLine(x + i);
}
}
public void M(int i)
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.i = i;
new Action<int>(<>c__DisplayClass0_.<M>g__Inner|0)(<>c__DisplayClass0_.i + 1);
}
Here, the compiler's spotted that it needs to create the delegate anyway, so it generates the same code as in the previous example.
Note that there are other cases where the compiler has to perform heap allocations when calling a local function, such as if the local function has to be resumable because it contains yield return or await statements.
To address the specific example in your edit:
int ParentFunction ()
{
int parentVarLambda = 0;
int parentVarLocal = 0;
Func<int> lamdaFuncion = () => parentVarLambda + 1;
int a = lamdaFuncion();
int b = LocalFunction();
return a + b;
int LocalFunction()
{
int localVar = 1;
return parentVarLocal += localVar;
}
}
We can again put this into SharpLab, and get:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public int parentVarLambda;
public int parentVarLocal;
internal int <ParentFunction>b__0()
{
return parentVarLambda + 1;
}
internal int <ParentFunction>g__LocalFunction|1()
{
int num = 1;
return parentVarLocal += num;
}
}
private int ParentFunction()
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.parentVarLambda = 0;
<>c__DisplayClass0_.parentVarLocal = 0;
int num = new Func<int>(<>c__DisplayClass0_.<ParentFunction>b__0)();
int num2 = <>c__DisplayClass0_.<ParentFunction>g__LocalFunction|1();
return num + num2;
}
Note that the compiler's realised that it had to create a new instance of a generated class for the delegate anyway, so it's just opted to deal with the local function in the same way at no extra cost. It doesn't make much difference in this case, but this technique is needed where the delegate and the local function capture the same variables - they need to be hoisted into the same generated class.
Because of this, both parentVarLambda and parentVarLocal were allocated on the same compiler-generated class, and localFuncVar just got optimized away (but would have been allocated on the stack in <ParentFunction>g__LocalFunction|1()).

What is the purpose of delegates and what are their advantages? [duplicate]

This question already has answers here:
When & why to use delegates? [duplicate]
(8 answers)
Closed 7 years ago.
Can anybody explain to me why we need delegates and what are the advantages of them?
Here is a simple program I have created with and without delegates (using plain methods):
Program with without delegates:
namespace Delegates
{
class Program
{
static void Main(string[] args)
{
abc obj = new abc();
int a = obj.ss1(1, 2);
int b = obj.ss(3,4);
Console.WriteLine("the result of ss is {0} and the result of ss1 is {1}", a, b);
Console.ReadKey();
}
}
class abc
{
public int ss(int i, int j)
{
return i * j;
}
public int ss1(int x, int y)
{
return x + y;
}
}
}
Program with Delegates:
namespace Delegates
{
public delegate int my_delegate(int a, int b);
class Program
{
static void Main(string[] args)
{
my_delegate del = new my_delegate(abc.ss);
abc obj = new abc();
my_delegate del1 = new my_delegate(obj.ss1);
int a = del(4, 2);
int b = del1(4, 2);
Console.WriteLine("the result of ss is {0} and the result of ss1 is {1}", a, b);
Console.ReadKey();
}
}
class abc
{
public int ss(int i, int j)
{
return i * j;
}
public int ss1(int x, int y)
{
return x + y;
}
}
}
Both programs give the same results, so what is advantage of using Delegates?
Thanks.
Delegate is designed to program in event-driven approach which creates a more decoupled source code.
With delegates, we can create something like publisher-subscriber pattern where subscribers can register to receive events from publishers.
We usually see delegates in use as event handlers. For example, with delegates we can create reusable controls by dispatching an event when something happens (e.x: click event,...), in this case, the control is the publisher, any code (subscriber) interested in handling this event will register a handler with the control.
That's one of the main benefits of delegates.
There are more usages pointed out by #LzyPanda in this post: When would you use delegates in C#?

Why am I getting these out parameter errors in C#?

I am new to C#. I've tried this with out parameter in C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class First
{
public void fun(out int m)
{
m *= 10;
Console.WriteLine("value of m = " + m);
}
}
class Program
{
static void Main(string[] args)
{
First f = new First();
int x = 30;
f.fun(out x);
}
}
but i get some errors like "Use of unassigned out parameter 'm'" and
The out parameter 'm' must be assigned to before control leaves the current method.
So what is the meaning of these errors and why it is compulsory to assign 'm' when i'm already assigned a value to x.
ref means that you are passing a reference to a variable that has been declared and initialized, before calling the method, and that the method can modify the value of that variable.
out means you are passing a reference to a variable that has been declared but not yet initialized, before calling the method, and that the method must initialize or set it's value before returning.
You're getting an error because a variable sent to a method as an out parameter does not have to be initialized before the method call. The following is 100% correct code:
class Program
{
static void Main(string[] args)
{
First f = new First();
int x;
f.fun(out x);
}
}
Looks like you're looking for ref instead of out here:
class First
{
public void fun(ref int m)
{
m *= 10;
Console.WriteLine("value of m = " + m);
}
}
class Program
{
static void Main(string[] args)
{
First f = new First();
int x = 30;
f.fun(ref x);
}
}
out parameters are for when the function wants to pass a value out of itself. What you want here is ref, which is when the function expects it to be passed in, but can change it.
For examples of how both are supposed to be used, read http://www.dotnetperls.com/parameter. It's explained in simple terms, and you should be able to get a good understanding of it.
You should note that in your code, you never access the variable after the function call, therefore ref doesn't actually do anything. Its purpose is to send changes back to the original variable.
As of C# 7.0 the ability to declare a variable right at the point where it is passed as an out argument was introduced.
Before:
public void PrintCoordinates(Point p)
{
int x, y; // have to "predeclare"
p.GetCoordinates(out x, out y);
WriteLine($"({x}, {y})");
}
C# 7.0
public void PrintCoordinates(Point p)
{
p.GetCoordinates(out int x, out int y);
WriteLine($"({x}, {y})");
}
You can even use var key word:
p.GetCoordinates(out var x, out var y);
Be carefull with the scope of out parameter. For example, in the following code, "i" is only used within if-statement:
public void PrintStars(string s)
{
if (int.TryParse(s, out var i)) { WriteLine(new string('*', i)); }
else { WriteLine("Cloudy - no stars tonight!"); }
}
Further information can be found here. This link is not only about out parameter, but all the new features introduced in c# 7.0
public void Ref_Test(ref int x)
{
var y = x; // ok
x = 10;
}
// x is treated as an unitialized variable
public void Out_Test(out int x)
{
var y = x; // not ok (will not compile)
}
public void Out_Test2(out int x)
{
x = 10;
var y = x; // ok because x is initialized in the line above
}

Categories

Resources