【C#】有关值类型的三个简单问题

记得之前写过一篇有关字典踩坑的文章。

实际上还是有关值类型的事情。这里再扩展三个相关的小问题,作为一个笔记记录下来。

        //辅助结构体。
        public struct Value
        {
            public int value;
            public void Add(int v)
            {
                value += v;
            }
        }
        //装箱拆箱
        public static void Q1()
        {
            Value v = new Value();

            void Method(ref object obj)
            {
                Value result = (Value)obj;
                result.Add(1);
                obj = result;
            }

            object obj = v;
            Method(ref obj);
            v.value.Log();//输出什么?
        }
        //闭包
        public static void Q2()
        {
            Value sum = new Value();
            Action act = null;

            for (int i = 0; i < 3; i++)
            {
                act += () => sum.Add(++i);
            }
            act.Invoke();
            sum.value.Log();//输出什么?
        }
        //数组和List
        public static void Q3()
        {
            var v = new Value();

            Value[] array = new Value[] { v };
            array[0].Add(1);
            array[0].value.Log();//输出什么?

            List<Value> list = new List<Value>() { v };
            list[0].Add(1);
            list[0].value.Log();//输出什么?

            v.value.Log();//输出什么?
        }

这里分别解释一下。

Q1是个有关装箱拆箱的问题。在装箱的时候,会将栈上的值复制到堆上,所以object obj = v这一步进行了拷贝,操作obj并不会影响原来的v;同样地,在拆箱的时候也会从堆上拷贝到栈上,所以Method内部,假设直接调用((Value)obj).Add(1)也不会影响obj。最后输出的就是0。

这里没有展开Method方法,是营造一种使用场景的氛围,表示这里装箱拆箱是为了传递方法参数。这个问题也表明了ref object并不能避免值类型的拷贝,因为在装箱拆箱的过程中就已经进行了拷贝。

Q2是有关闭包的问题。委托中以引用的形式捕获了外部的变量i,所以在Invoke执行时,每次的i获取的都是引用值。在For循环结束后i是3,每次++i又增加了i值。所以输出值为4+5+6=15。如果写一个临时变量int temp=++i,那么就会生成3个不同的临时变量被闭包捕获,输出值就是1+2+3=6了。

有次别人问我一个类似的问题,在循环中为十个按钮分别注册输出事件,说是有过一定实际开发经历的人才能做对。我也是经常忘记一些特性,然后再验证,再忘记这样。好在现在一些知识性的内容可以直接问AI,节省了不少时间。

Q3是一个涉及数组和List的问题。老实说我一开始都不知道是这样的输出结果,把问题抛给DeepSeek-0528一样没回答对。三个输出分别是1,0,0。这似乎涉及到数组的访问细节:尽管这里并没有使用ref array[0]的访问方法,但访问到的仍然是引用;而list[0]访问到的是值的拷贝,所以并没有作用。此外,这里数组可以直接使用array[0].value=1这样的赋值方式,而list则不能。

尽管使用值类型可能在各种意想不到的地方出问题,但用好了也确实方便高效。

© 版权声明
THE END
喜欢就点个赞吧
点赞0 分享
评论 共1条

请登录后发表评论

    暂无评论内容