结构变量作为方法的参数调用,在方法内部使用的“坑”你遇到过吗?-阿里云开发者社区

开发者社区> 橘子红了呐> 正文

结构变量作为方法的参数调用,在方法内部使用的“坑”你遇到过吗?

简介:
+关注继续查看

很久没有写博了,今天一个同学在问结构变量的问题,问结构到底是传递值还是传递引用。查过MSDN的都知道,结构默认是传递值的,因此在方法内部,结构的值会被复制一份。但是对于结构数组,如果值还是要被复制一份,这个内存占用是不是很多了呢?
一般来说,数组参数传递的是引用,那么数组的元素呢?它是被复制的还是被引用的?如果结构数组的元素象结构变量那样也是复制的,那么对于方法调用的内存占用问题,就得好好考虑下了。

MSDN看了半天,也讨论了半天,感觉还是没有动手实验最有说服力,我们先定义一个结构体:

复制代码
struct Point
    {
        public int X;
        public int Y;
        public Point(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
    }
复制代码

定义2个方法,分别以传值和传引用的方式来调用结构变量:

复制代码
        static void TestStruc(Point p)
        {
            p.X++;
            p.Y++;

        }

        static void TestStruc2(ref Point p)
        {
            p.X++;
            p.Y++;

        }
复制代码

调用代码:

复制代码
            Point p = new Point(1, 2);
            TestStruc(p);
            Console.WriteLine("call by value Point X={0},Y={1}", p.X, p.Y);

            TestStruc2(ref p);
            Console.WriteLine("call by ref Point X={0},Y={1}", p.X, p.Y);
复制代码

调用结果符合预期,以引用传递的结构变量,它的值被改变了:

Struct Pont(X,Y) Test:
call by value Point X=1,Y=2
call by ref Point X=2,Y=3

 

下面,试试结构数组,看有何不同:

复制代码
        static void TestStrucArray2(ref Point[] arr)
        {
            Point p = arr[0];
            p.X++;
            p.Y++;

        }
复制代码

调用代码:

复制代码
            Point[] arr = new Point[2];
            arr[0] = new Point(1, 2);
            arr[1] = new Point(3, 4);

            TestStrucArray(arr);
            Console.WriteLine("call by value Point[0]: X={0},Y={1}", arr[0].X, arr[0].Y);
复制代码

结果:

call by value Point[0]: X=1,Y=2

方法内部对结果数组元素的改变无效,难道结构数组被复制了?

惊出一身冷汗!

改成引用参数的方式来试试,避免复制结构数组:

复制代码
       static void TestStrucArray2(ref Point[] arr)
        {
            Point p = arr[0];
            p.X++;
            p.Y++;

        }
复制代码

结果:

call by value Point[0]: X=1,Y=2
call by ref Point[0]: X=1,Y=2

引用方式数组还是被复制了?看来哪里有问题阿。

去掉用一个结构变量来引用结构数组的成员,直接操作结构数组的元素,来看看调用结果:

复制代码
        static void TestStrucArray3( Point[] arr)
        {
            //Point p = arr[0];
            arr[0].X++;
            arr[0].Y++;

        }

        static void TestStrucArray4(ref Point[] arr)
        {
            arr[0].X++;
            arr[0].Y++;

        }
复制代码

调用代码:

复制代码
            TestStrucArray4(ref arr);
            Console.WriteLine("call by ref Point[0] not use var : X={0},Y={1}", arr[0].X, arr[0].Y);
            arr[0].X = 1; arr[0].Y = 2;

            TestStrucArray3( arr);
            Console.WriteLine("call by var Point[0] not use var : X={0},Y={1}", arr[0].X, arr[0].Y);
复制代码

 

结果:

call by ref Point[0] not use var : X=2,Y=3
call by var Point[0] not use var : X=2,Y=3

直接操作结构数组的元素,元素的值被改变了,证明结构数组没有复制数组元素的值,依然是对数组的引用,上面的问题虚惊一场。

我们对比下前后不同的代码,发现TestStrucArray2 仅仅多了一行代码:

复制代码
       static void TestStrucArray2(ref Point[] arr)
        {
            Point p = arr[0];
            p.X++;
            p.Y++;

        }
复制代码

这说明,定义一个结构变量,让另外一个结构变量的值赋值给它,等于是复制这个结构变量的值。

往往有时候,我们为了敲代码方便,少写几个字,便定义一个临时变量去引用原来的变量,而这种行为,对于操作结构变量,无疑是一个最大的坑,这个坑,你遇到过吗?

 

 

 


    本文转自深蓝医生博客园博客,原文链接:http://www.cnblogs.com/bluedoctor/p/3205058.html,如需转载请自行联系原作者


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
4.4、Libgdx使用方法查询运行环境相关属性
(原文:http://www.libgdx.cn/topic/46/4-4-libgdx%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%E6%9F%A5%E8%AF%A2%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83%E7%9B%B8%E5%85%B3%E5%B1%9E%E6%80%A7) Application接口提供了多种方法查询运行环境的属性。
792 0
Rtti 单元(2)调用类的方法, 读写属性值
通过 Rtti 还能够调用一个类的方法, 也能读取或设置其属性值. unit Unit1;  interface  uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Co...
651 0
C# 调用存储过程操作 OUTPUT参数和Return返回值
本文转载:http://www.cnblogs.com/libingql/archive/2010/05/02/1726104.html   存储过程是存放在数据库服务器上的预先编译好的sql语句。使用存储过程,可以直接在数据库中存储并运行功能强大的任务。
863 0
3404
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载
《2021云上架构与运维峰会演讲合集》
立即下载