Why didn't this line of code update the object? [duplicate] - c#

This question already has answers here:
What do ref, val and out mean on method parameters?
(4 answers)
Closed 6 years ago.
Given that there is a class called Point with a float x and float y component.
class Point
{
public double x;
public double y;
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
public Point()
{
x = y = 0;
}
public override string ToString()
{
return string.Format("({0:F2},{1:F2})", x, y);
}
}
Why in the mystery1 function didn't the point p1 get updated to be (11.00, 11.00) since p.x is 11 from the first line?
{
Point p1 = new Point(11, 22);
Point p2 = p1;
int n1 = 33;
int n2 = n1;
mystery1(p1, n1);
Console.WriteLine("n1 = {0}, n2 = {1}", n1, n2);
Console.WriteLine("p1 = {0}, p2 = {1}", p1, p2);
mystery2(p2, n2);
Console.WriteLine("n1 = {0}, n2 = {1}", n1, n2);
Console.WriteLine("p1 = {0}, p2 = {1}", p1, p2);
}
static void mystery1(Point p, int n)
{
n = (int)p.x;
p = new Point(n, n);
}
static void mystery2(Point p, int n)
{
p.x = 77;
n = 88;
}

Point is a value type. so when you call a method with a point as parameter, you have a new instance of the point in the method. So you are changing the values not on that instance that you have in the main method.
Have a look at the ref keyword: https://msdn.microsoft.com/en-us/library/0f66670z.aspx
Also at the moment you make a new instance with new Point(n, n); you create even one more instance of point .
You main method still points to the old object which is not getting changed.
Also I would recommend that you have a general look at the differences between value and complex types like here: https://msdn.microsoft.com/en-us/library/34yytbws(v=vs.100).aspx
or here:
https://msdn.microsoft.com/en-us/library/s1ax56ch.aspx

In C# all paramaters are passed by value, even references.
That means when you pass an instance of a class to a method you pass the reference of that instance as value. Imagine the reference (similar to a pointer) is simply the adress of an instance within the stack stored into a string (it´s not a string, but for simplicity let´s assume so). Now when you change that string what should happen to the outside? Nothing, because the string is just a value, it does not have anything to do with your actual referenced instance. This sounds weird, but that´s it. In your msyter1-method you simply re-assign this reference to a new instance, however you simply change the value of that reference, not the reference itself.
You could do this by passing the class by reference`:
static void mystery1(ref Point p, ref int n)
Now changes within the method are reflected to the outer of the method.
In mystery2 there´s a difference and you won´t need the ref-keyword for your Point-class, because you´re not changing the reference itself but a property of the referenced instance. However this does not apply to the integer-argument which is of course a value-type and thus must be passed by ref to be updated outside your method also:
static void mystery2(Point p, ref int n)

Related

Beginner question about a task in a course in C#

The code
class Program
{
static int Add(int x, int y)
{
x = 4;
y = 3;
int f = x + y;
return f;
}
static void Main(string[] args)
{
int x = 4;
int y = 3;
Console.WriteLine("Answer: ");
Add(x, y);
}
}
Doing a beginner course in C# and I have been stuck at this question for two days now.
I know its probably really simple, but I have tried so many different things that I think I have made it harder for me than it really.
I fixed to call strings in methods, but numbers seems hard.
The task is about to take two numbers in and that return the answer.
Tried searching around all the different errors I got with all the different tries, but didn't find the help, or the answers I understand.
You almost did all of it, just with 2 issues.
You should relay on the numbers you pass from Main to Add and not reassign the values inside Add otherwise passing them is useless and unusable for other numbers.
Add returns a value but you never save it + print it.
Example for #1
static int Add(int x, int y)
{
int f = x + y;
return f;
}
Example of #2
var result = Add(x, y);
Console.WriteLine(result);
Corrected Example:
class Program
{
static int Add(int x, int y)
{
// You don't need to redefine the variables x and y,
// because you get them when you call the method
// You can shorten the last part
// and just return the Addition
return x + y;
}
static void Main(string[] args)
{
int x = 4;
int y = 3;
// Prints the Word Answer
// as well as the Addition result into the Console now
Console.WriteLine("Answer: " + Add(x, y));
}
}
Your Errors:
You never printed the Result into the Console!
You shouldn't redefine the variables in the Function, because if you do that you don't need to use a function in the first place
You can shorten the return statement (you don't have to)
You can add Add(x,y) into the Console.WriteLine because it returns a Integer, therefore it is basically like writting Console.WriteLine("Answer: " + 7);
Here is an working version with explaination:
class Program
{
static int Add(int x, int y)
{
//x = 4; these are passed in as parameter, no need to set it
//y = 3;
int f = x + y;
return f;
}
static void Main(string[] args)
{
int someX = 4; //these are only known inside the scope of "Main"
int someY = 3;
int result = Add(someX, someY); //these are passed inside the function,
//the value is copied
Console.WriteLine("Answer: " + result.ToString());
}
}
You can do it even easier and simple In addition , this answer is more dynamic as you can choose the two numbers every time you run the program:
class Program
{
static int Add(int x, int y)
{
return x + y;
}
static void Main(string[] args)
{
Console.WriteLine("Answer: " + Add(Convert.ToInt32(Console.ReadLine()),
Convert.ToInt32(Console.ReadLine())).ToString());
Console.ReadLine(); //In order to be able to see the result in the screen
}
}

Value Tuple initialization is counter-intuitive

In the Sunday evening I have been watching some conferences this time I get hands on this one Conference Link
Where I found out pretty interesting think there is simple code example:
struct Point
{
private double x;
public double X { get => x; set => x = value; }
private double y;
public double Y { get => y; set => y = value; }
public Point(double x, double y) => (this.x, this.y) = (x, y);
public void SwapCode() => (X, Y) = (Y, X);
}
In Main:
var point = new Point(10.0, 11.0);
Console.WriteLine($"x: {point.X}, y: {point.Y}");
point.SwapCode();
Console.WriteLine($"x: {point.X}, y: {point.Y}");
And there is output of this :
x: 10, y: 11
x: 11, y: 10
So there is some questions:
How does it works ?
What I mean by that is Tuples should be translate into Tuple<T, K> which should be initialize with copy of the values but there it assign values to the variables at least for me it's kind of counter intuitive.
And i wonder if it's just sugar syntax think or there is happen some magic under this what make perfect sense but I can't spot it out?
Firstly structs should be immutable. Even though you can do this, you probably shouldn't.
Secondly, your SwapCode is actually doing this, as seen here.
public void SwapCode()
{
double num = Y;
double num2 = X;
double num4 = X = num;
num4 = (Y = num2);
}
Yeah, it's a little strange. However, it's just a little syntactic magic introduced in C#7. What it is actually doing is using a deconstruct method (the terminology .Net uses) to provide a set of out arguments for each of the params you want to extract. In this case, it's the properties/field you supplied!
To see it a little clearer, consider these two functionally equivalent code blocks
(int x, int y) asd = (1, 2); // create a Value Tuple
(int x, int y) = asd; // deconstruct it
(x, y) = (x, y); // assign to the deconstructed type
// All the above now has the swapped values
// they are all pointing to the same variables/memory
// You could even take this further by
x = 10;
y = 11;
// Once again, x and y, asd, and (x, y) all have the same values
// Because they are the same
// ----------------------------------------------------
int x = 1;
int y = 2;
(x, y) = (y, x); // we are just deconstructing our original variables
// All the above now has the swapped values
// they are all pointing to the same variables/memory
Note : As you can see, this is also a slightly more succinct way of swapping 2 variables as you don't have to use a temp variables, your friendly CLR does it for you
Anyway, you shouldn't be doing this with a struct anyway, they really should be immutable for various reasons

Get name of delegate method

Out of curiosity I've been looking into delegate methods and am interested in getting the name of the current delegate method that is being used (just for fun, really).
The code I have is as follows (with the current/desired outputs):
private delegate int mathDelegate(int x, int y);
public static void Main()
{
mathDelegate add = (x,y) => x + y;
mathDelegate subtract = (x,y) => x - y;
mathDelegate multiply = (x,y) => x * y;
var functions = new mathDelegate[]{add, subtract, multiply};
foreach (var function in functions){
var x = 6;
var y = 3;
Console.WriteLine(String.Format("{0}({1},{2}) = {3}", function.Method.Name, x, y, function(x, y)));
}
}
/// Output is:
// <Main>b__0(6,3) = 9
// <Main>b__1(6,3) = 3
// <Main>b__2(6,3) = 18
/// Desired output
// add(6,3) = 9
// subtract(6,3) = 3
// multiply(6,3) = 18
Does anyone know of any way(s) I could achieve this? Thanks.
Your methods are anonymous delegates, so the the compiler gives each of them a name that doesn't have any meaningful connection back to the variable name. If you want them to have better names then make them actual methods:
public int Add(int x, int y)
{
return x + y ;
}
etc. Then reference them by name:
var functions = new mathDelegate[]{this.Add, this.Subtract, this.Multiply};
Note that the this. is optional but illustrates that they are class members rather than local variables.

Array and List discrepencies with structs

In the following code, a struct is obtained from an array and from a list. When getting the item by index, the array appears to do it by reference whereas the list appears to do it by value. Can someone explain the reasoning behind this?
struct FloatPoint {
public FloatPoint (float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
public float x, y, z;
}
class Test {
public static int Main (string[] args) {
FloatPoint[] points1 = { new FloatPoint(1, 2, 3) };
var points2 = new System.Collections.Generic.List<FloatPoint>();
points2.Add(new FloatPoint(1, 2, 3));
points1[0].x = 0; // not an error
points2[0].x = 0; // compile error
return 0;
}
}
Changing the struct definition to a class makes both compile.
When you get a struct, it is always by value. The structure will be copied, you don't get a reference to it.
The difference is that you can access the sctruct directly in the array, but not in the list. When you change the property in the struct in the array, you access the property directly, but to do the same with a list you have to get the struct, set the property, then store the struct back in the list:
FloatPoint f = points2[0];
f.x = 0;
points2[0] = f;
Earlier versions of the compiler would let you write the code that you have, but for a list it would generate code similar to this:
FloatPoint f = points2[0];
f.x = 0;
I.e. it would read the struct, change it, and silently throw the changed struct away. The compiler was changed to give an error in that case.

Is swap method in C# whose parameters have value type not efficient?

Check this method:
public static void Swap(ref int i, ref int j)
{
int aux=i;
i=j;
j=aux;
}
Is it more efficient than this?
public static void Swap1(int[] a, int i, int j)
{
int aux=a[i];
a[i]= a[j];
a[j]=aux;
}
I'm using these methods like this:
static void Main(string[] args)
{
int[] a = { 5, 4, 3, 1 };
Swap(a[1], a[2]);
Swap(a, 1, 2);
}
Which of these methods is more efficient and why?
Your method will not swap any parameters at all. I mean it will swap parameters inside your method, but it will not affect the values of source parameters. That's because value types are copied when they are passed into methods. Here's the example:
void IncorrectSwap(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
void HereHappensNothing()
{
int a = 1;
int b = 2;
IncorrectSwap(a, b);
// a still = 1, and b = 2, nothing happens
}
To make your method work you have to pass value types by reference like that:
void CorrectSwap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
void HereSwapHappens()
{
int a = 1;
int b = 2;
CorrectSwap(ref a,ref b);
// a = 2, and b = 1, Ok.
}
Here you can read about value types and how to work with them.
Update
Following your update. I don't think there should be any significant difference in performance as long as value types don't get boxed when passed by ref. There can be some penalty when you pass more parameters, but I don't think it should be significant, you will not see the difference.
Not passing by ref will not work. As you will only be affecting the local parameters.
Your code does nothing!
When parameters are passed by value you can't change them.
So to correctly implement Swap you need to pass by ref.

Categories

Resources