简体   繁体   English

结构和接口中的C#getters / setter

[英]C# getters/setters in structs and interfaces

I came along an (according to me) strange difference between structs and interfaces in C#. 我来了(根据我)C#中的结构和接口之间的奇怪区别。 Consider this interface and struct: 考虑这个接口和结构:

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 a Number as property, use the ChangeNumber method to change n to 2 and print the number by using Log, it prints 0 instead: 当我使用Number作为属性创建一个新类时,使用ChangeNumber方法将n更改为2并使用Log打印该数字,它将打印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 realised it was because when I call this.Number.ChangeNumber(2); 过了一会儿,我意识到这是因为我打电话给this.Number.ChangeNumber(2); , I actually create a new object (because of the getter) and change that number to 2. But then I changed a little bit of the code by changing the Number property to an INumber property: ,我实际上创建了一个新对象(因为getter)并将该数字更改为2.但后来我通过将Number属性更改为INumber属性来更改了一些代码:

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! 在这种情况下,它打印2! Why is this happening? 为什么会这样? Doesn't the same principal of structs apply to the interface? 结构的相同原理是否适用于界面?

The difference is that struct is used as a value type, where interface (which can be implemented by a class or a struct) is a reference type. 不同之处在于struct用作值类型,其中interface (可以通过类或结构实现)是引用类型。

That makes a huge difference in your example. 这对你的例子产生了巨大的影响。 What you are doing in the first case the call to this.Number means "Get me the value of the number" - which means it pulls the value on stack, and the (unnamed) variable on stack, which is not stored anywhere, gets modified. 在第一种情况下你正在做什么调用this.Number意味着“获取数字的值” - 这意味着它在堆栈上提取值,并且堆栈上的(未命名的)变量(不存储在任何地方)得到改性。

In the other case, the interface is a reference type - which means, it gets whatever is stored on its address and modifies it. 在另一种情况下,接口是一个引用类型 - 这意味着它获取存储在其地址上的任何内容并对其进行修改。

Generally I would not suggest having a mutable struct (as already mentioned in comments). 一般来说,我不建议使用可变struct (如评论中已提到的)。

You can read more on this topic eg here: Why are mutable structs “evil”? 你可以在这里阅读更多关于这个主题的内容,例如: 为什么可变结构“邪恶”?

This is caused by auto property in NumberContainer class, you always get a copy of value when you are accessing property. 这是由NumberContainer类中的auto属性引起的,当您访问属性时,总是会获得值的副本。

If you change property to a field, it works as expected . 如果将属性更改为字段,则按预期工作 Remember that autoproperty is just pair of methods, and that value types are copied when returned/passed to/from any method. 请记住,autoproperty只是一对方法,并且在返回/传递给任何方法时都会复制该值类型。

When you are calling 当你打电话的时候

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

you are actualy calling: 你实际上是在打电话:

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

    this.getNumber()
        .Log();

When you are using interface you are returning reference to an object, so operations are always performed on the same object. 当您使用接口时,您将返回对对象的引用,因此始终对同一对象执行操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM