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

时间:2016-01-20 17:37:48

标签: c# struct interface getter

我来了(根据我)C#中的结构和接口之间的奇怪区别。考虑这个接口和结构:

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);
    }
}

当我使用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...
    }
}

过了一会儿,我意识到这是因为当我调用this.Number.ChangeNumber(2);时,我实际创建了一个新对象(因为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!
    }
}

在这种情况下,它打印2!为什么会这样?结构的相同原理是否适用于界面?

2 个答案:

答案 0 :(得分:4)

不同之处在于struct用作值类型,其中interface(可以由类或结构实现)是引用类型。

这对你的例子产生了巨大的影响。你在第一种情况下所做的事情this.Number的调用意味着"给我数字的价值" - 这意味着它会在堆栈上提取值,而堆栈上的(未命名的)变量(未存储在任何地方)会被修改。

在另一种情况下,接口是一个引用类型 - 这意味着,它获取存储在其地址上的任何内容并对其进行修改。

一般来说,我不建议使用可变struct(如评论中已提到的)。

您可以阅读有关此主题的更多信息,例如在这里:Why are mutable structs “evil”?

答案 1 :(得分:2)

这是由NumberContainer类中的自动属性引起的,当您访问属性时,您始终会获得值的副本。

如果您将属性更改为字段,则按预期工作。请记住,autoproperty只是一对方法,并且在返回/传递给任何方法时都会复制这些值类型。

当你打电话时

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

你正在致电:

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

    this.getNumber()
        .Log();

当您使用接口时,您将返回对对象的引用,因此始终对同一对象执行操作。