>백엔드 개발 >C#.Net 튜토리얼 >C# 기본 지식 정리 기본 지식(19) 값 유형의 박싱 및 언박싱(2)

C# 기본 지식 정리 기본 지식(19) 값 유형의 박싱 및 언박싱(2)

黄舟
黄舟원래의
2017-02-11 13:55:571654검색

코드가 컴파일러에 의해 반복 박싱을 발생시키는 경우 수동 박싱으로 변경하여 코드 실행 속도를 높일 수 있습니다.

            //手动装箱
            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));

이전 코드 세그먼트를 통해 작성할 수 있습니다. 프로그래밍할 때 값 유형을 boxing해야 하는 경우를 쉽게 알 수 있습니다. 값 유형에 대한 참조를 얻으려는 경우 권투에 지나지 않습니다. 값 유형과 참조 유형의 차이점은 여기에서도 명확하게 확인할 수 있습니다.
1. 값 유형은 관리되는 힙에 공간을 할당하지 않지만 참조 유형은 인스턴스화 후 클래스에 지정된 멤버를 할당합니다.
2. 값 유형에는 힙에 있는 추가 개체 구성원, 즉 "유형 개체 포인터" 및 "동기화 인덱스"가 없습니다.
Unboxed 값 유형에는 동기화된 인덱스가 없으므로 해당 유형이 있는 클래스의 메서드(예: 잠금)를 사용하여 여러 스레드가 이 인스턴스에 대한 액세스를 동기화하도록 허용할 수 없습니다.
박스 처리되지 않은 값 유형에는 유형 개체 포인터가 없지만 Equals, GetHashCode 및 ToString과 같이 유형에 의해 상속되거나 재정의된 가상 메서드를 계속 호출할 수 있습니다. 값 형식이 이러한 가상 메서드 중 하나를 재정의하는 경우 값 형식이 암시적으로 봉인되어 어떤 형식도 파생될 수 없기 때문에 CLR은 해당 메서드를 비가상적으로 호출할 수 있습니다. 또한 가상 메서드를 호출하는 데 사용되는 값 형식 인스턴스는 boxing되지 않습니다. 재정의된 가상 메서드가 기본 클래스에서 메서드 구현을 호출하는 경우 기본 클래스 구현이 호출될 때 값 형식 인스턴스가 박싱됩니다. 이러한 메서드는 System.Object에 의해 정의되므로 이 메서드는 this 인수가 힙의 개체에 대한 포인터일 것으로 예상합니다.
또한 값 유형의 unboxed 인스턴스를 해당 유형의 인터페이스 중 하나로 캐스팅하려면 인스턴스를 boxing해야 합니다. 인터페이스 변수에는 힙의 개체에 대한 참조가 포함되어야 하기 때문입니다. 다음 코드를 보세요:

 class Program
    {
        static 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) 값 유형의 Boxing 및 Unboxing(2)에 대한 내용입니다. PHP 중국어 홈페이지(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.