• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

C#基础知识整理 基础知识(19) 值类型的装箱和拆箱(二)

c# 搞代码 4年前 (2022-01-09) 20次浏览 已收录 0个评论

如果代码中会造成编译器的反复装箱,可改为手动装箱,这样来使代码执行更快,看下面代码:

            //手动装箱            Int32 v = 5;            //由于string.Format的参数是object类型,所以这里会造成三次装箱。            Console.WriteLine(string.Format("{0},{1},{2}", v, v, v));            //修改一下,当然这只是一个小技巧,比如程序中对同一个值的同一个操作执行多次,            //应该都是要先执行一次,然后再使用的。            Object o = v;//装箱一次            Console.WriteLine(string.Format("{0},{1},{2}", o, o, o));

通过前面的代码段,我们再写程序时就很容易判断什么时候值类型要装箱。无非就是当要获取一个值类型的引用时,就要装箱。这里也很清楚的可以看出值类型与引用类型的区别:
1、值类型不在托管堆中分配空间;而引用类型在实例化后就在堆上分配了类中指定的成员的的空间。
2、值类型没有堆上的对象的额外成员,即“类型对象指针”、“同步索引”。
未装箱的值类型没有同步索引,因此不能使用该类型所在类的方法(比如lock)让多个线程同步对这个实例的访问。
虽然未装箱的值类型没有类型对象指针,但仍可调用由类型继承或重写的虚方法,比如Equals,GetHashCode,ToString。如果值类型重写了其中任何一个虚方法,那么CLR可以非虚地调用该方法,因为值类型是隐式密封的,没有任何类型能够从它派生。此外,用于调用虚方法的值类型实例不会被装箱。如果重写的虚方法要调用方法在基类中的实现,那么在调用基类的实现时,值类型实例会装箱。因为这些方法是有System.Object定义的,所以这些方法期望this实参是指向堆上的一个对象的指针。
此外,将值类型的一个未装箱实例转型为类型的某个接口是,要求实例进行装箱。因为接口变量必须包含对堆上的一个对象的引用。看下面代码:

 class Program    {        sta<i style="color:transparent">本文来源gaodai$ma#com搞$代*码*网(</i>tic void Main(string[] args)        {            Point p1 = new Point(10, 10);            Point p2 = new Point(20, 20);            //调用ToString不装箱,这里ToString是一个虚方法            Console.WriteLine(p1.ToString());            //GetType是一个非虚方法,p1要装箱            Console.WriteLine(p1.GetType());            //这里调用的是public int CompareTo(Point p)            //p2不会装箱            Console.WriteLine(p1.CompareTo(p2));            //p1要装箱,这就是将未装箱的值类型转为类型的某个接口时            IComparable c = p1;            Console.WriteLine(c.GetType());            //这里调用的是public Int32 CompareTo(Object o),            //而且c本来就是一个引用,因此不装箱了            Console.WriteLine(p1.CompareTo(c));            //这里调用的是c的CompareTo方法,参数是object型的            //所以要对p2装箱            Console.WriteLine(c.CompareTo(p2));            //对c拆箱,并复制值到p2中            p2 = (Point)c;            Console.WriteLine(p2.ToString());        }    }         internal struct Point : IComparable    {        private Int32 x;        private Int32 y;        public Point(Int32 x, Int32 y)        {            this.x = x;            this.y = y;        }        public override string ToString()        {            return string.Format("{0},{1}", x, y);//这里装箱两次,不知道有没好办法。        }        public int CompareTo(Point p)        {            return Math.Sign(Math.Sqrt(x * x + y * y) - Math.Sqrt(p.x * p.x + p.y * p.y));        }        public Int32 CompareTo(Object o)        {            if (GetType() != o.GetType())            {                throw new ArgumentException("o is not Point.");            }            return CompareTo((Point)o);        }    }

以上就是C#基础知识整理 基础知识(19) 值类型的装箱和拆箱(二)的内容,更多相关内容请关注搞代码(www.gaodaima.com)!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:C#基础知识整理 基础知识(19) 值类型的装箱和拆箱(二)
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址