C # getters / setters in structures and interfaces

I met (for me) a strange difference between structures and interfaces in C #. Consider this interface and structure:

public interface INumber { void ChangeNumber(int n); void Log(); } public struct Number : INumber { private int n; public void ChangeNumber(int n) { this.n = n; } public void Log() { Console.WriteLine(this.n); } } 

When I create a new class with the Number as property, use the ChangeNumber method to change n to 2 and print the number using Log, instead it prints 0:

 public class NumberContainer { public Number Number { get; set; } public NumberContainer() { this.Number = new Number(); this.Number.ChangeNumber(2); this.Number.Log(); //prints 0... } } 

After a while, I realized that when I call this.Number.ChangeNumber(2); , I actually create a new object (due to getter) and change it to 2. But then I changed the code a bit by changing the Number Property for the INumber property:

 public class NumberContainer { public INumber Number { get; set; } public NumberContainer() { this.Number = new Number(); this.Number.ChangeNumber(2); this.Number.Log(); //prints 2! } } 

In this case, it prints 2! Why is this happening? Does the same principle of structures apply to an interface?

+5
source share
2 answers

The difference is that struct used as a value type, where interface (which can be implemented by a class or structure) is a reference type.

This is of great importance in your example. What you do in the first case, calling this.Number means “Get me the value of the number” - this means that it pulls the value on the stack, and the (unnamed) variable on the stack that is not stored anywhere gets modified.

In another case, the interface is a reference type - this means that it receives everything that is stored at its address and modifies it.

In general, I would not suggest having a mutable struct (as mentioned in the comments).

You can read more on this topic, for example. here: Why are volatile structures "evil"?

+4
source

This is caused by the auto property in the NumberContainer class, you always get a copy of the value when accessing the property.

If you change a property in a field, it works as expected . Remember that autoproperty is just a couple of methods, and these types of values ​​are copied when returning / passing to / from any method.

When you call

  this.Number.ChangeNumber(2); this.Number.Log(); //prints 0... 

you really call:

  this.getNumber() // returns copy of value type .ChangeNumber(2); // executes op on that copy this.getNumber() .Log(); 

When you use the interface, you return a reference to the object, so operations are always performed on the same object.

+2
source

Source: https://habr.com/ru/post/1241056/


All Articles