C#容易忽视的拆装箱问题

在值类型的拆装箱中,有些问题容易被忽视

interface IAngle
{
    void MoveTo(int degress, int minutes, int seconds);
}
struct Angle : IAngle
{
    private int _Degress;
    private int _Minutes;
    private int _Seconds;
    public void MoveTo(int degress, int minutes, int seconds)
    {
        _Degress = degress;
        _Minutes = minutes;
        _Seconds = seconds;
    }
    public override string ToString()
    {
        return _Degress.ToString();
    }
}
class Program
{
    static void Main()
    {
        Angle angle = new Angle();
        angle.MoveTo(25, 30, 88);
        //#Expamle 1
        object objectangle = angle;
        Console.WriteLine(((Angle)objectangle).ToString());

        //#Expamle 2
        ((Angle)objectangle).MoveTo(28, 30, 88);
        Console.WriteLine(((Angle)objectangle).ToString());

        //#Expamle 3
        ((IAngle)angle).MoveTo(28, 30, 88);
        Console.WriteLine(((IAngle)angle).ToString());

        //#Expamle 4
        ((IAngle)objectangle).MoveTo(28, 30, 88);
        Console.WriteLine(((Angle)objectangle).ToString());
    }
}
// Print:
// 25
// 25
// 25
// 28

在上面的代码中 使用IAngle接口创建了Angle结构,然后在Main函数中使实例化使用了Angle中的方法三次 最后代码输出的结果让人疑惑

在Expamle1中装箱了Angle类型的实例为 object 然后在Console.WriteLine里产生了拆箱操作,此时输出的是obj的副本

Expamle2里使用了拆箱,产生了拷贝,然后调用了拷贝的值里面的方法 原有的objectangle并未被修改,被修改的是拆箱操作时候创建的值拷贝,运行完后已经被抛弃(赋值给_)

Expamle3里产生了装箱操作,也产生了拷贝

Expamle4里强制转换是向引用类型转换,不会产生拷贝,输出了预期的结果

具体查看下图

405945010549.png