検索
ホームページバックエンド開発C#.Net チュートリアルC#基礎知識編 基礎知識(18) 値型のボックス化とアンボックス化(1)

ボックス化とボックス化解除について詳しく知ることは、実際には非常に興味深いことです。まず、ボックス化とボックス化解除がなぜ起こるのか見てみましょう。
次のコードを見てください:

    class Program
    {
        static void Main(string[] args)
        {
            ArrayList array = new ArrayList();

            Point p;//分配一个

            for (int i = 0; i < 5; i++)
            {
                p.x = i;//初始化值

                p.y = i;

                array.Add(p);//装箱
            }
        }
    }

    public struct Point
    {
        public Int32 x;

        public Int32 y;
    }

5 回ループし、毎回 Point 値タイプのフィールドを初期化し、それを ArrayList に入れます。 Structは値型の構造体ですが、ArrayListには何が格納されるのでしょうか? ArrayList の Add メソッドをもう一度見てみましょう。 MSDN で Add メソッドを参照できます:
public virtual int Add(Object value),
Add のパラメータが Object 型であることがわかります。つまり、必要なパラメータはオブジェクトへの参照です。つまり、ここでのパラメータは参照型である必要があります。参照型とは何かについては、詳しく説明する必要はありません。それはヒープ上のオブジェクトへの参照にすぎません。ただし、理解を容易にするために、ヒープとスタックについてもう一度話しましょう。
1. スタック領域 (スタック) - コンパイラーによって自動的に割り当ておよび解放され、関数のパラメーター値、ローカル変数値などが格納されます。
2. ヒープ領域(ヒープ) - プログラマによって割り当てられ、解放されます。プログラマが解放しない場合、プログラムの終了時に OS によって再利用される可能性があります。
例:

    class Program
    {
        static void Main(string[] args)
        {
            Int32 n;//这是值类型,存放在栈中,Int32初始值为0
            
            A a;//此时在栈中开辟了空间

            a = new A();//真正实例化后的一个对象则保存在堆中。
        }
    }

    public class A
    {
        public A() { }
    }

上記の質問に戻りますが、Add メソッドには参照型のパラメーターが必要です。どうすればよいでしょうか?次に、ボックス化を使用する必要があります。いわゆるボックス化とは、値型を参照型に変換することです。変換プロセスは次のとおりです:
1. マネージド ヒープにメモリを割り当てます。割り当てられるメモリ量は、値型の個々のフィールドで必要なメモリ量に、マネージド ヒープ内のすべてのオブジェクトが持つ 2 つの追加メンバー (型オブジェクト ポインターと同期ブロック インデックス) で必要なメモリ量を加えたものです。
2. 値の型フィールドを新しく割り当てられたメモリにコピーします。
3. オブジェクトのアドレスを返します。この時点で、アドレスはオブジェクトへの参照であり、値の型は参照型に変換されています。
このようにして、Add メソッドで、ボックス化された Point オブジェクトへの参照が保存されます。ボックス化されたオブジェクトは、プログラマが処理するか、システムのガベージ コレクションがそれを処理するまで、ヒープ内に残ります。この時点で、ボックス化された値型の有効期間は、ボックス化されていない値型の有効期間を超えます。
上記のボックス化では、配列の 0 番目の要素を取り出したい場合は、当然ボックス化を解除する必要があります。
Point p = (Point)array[0]; ここで行う必要があるのは、参照を取得することです。 ArrayList の要素 0 にそれを Point 値型 p に入れます。この目標を達成するには、どのように実装すればよいでしょうか。まず、ボックス化された Point オブジェクトの各 Point フィールドのアドレスを取得します。開梱はこれで終わりです。これらのフィールドに含まれる値は、ヒープからスタックベースの値型インスタンスにコピーされます。アンボックス化は本質的に、オブジェクトに含まれるプリミティブ値型への参照を取得するプロセスです。実際、参照はボックス化されたインスタンスのボックス化されていない部分を指します。したがって、ボックス化とは異なり、ボックス化解除ではメモリ内のバイトをコピーする必要がありません。ただし、もう 1 つの点があります。ボックス化解除直後にフィールド コピー操作が発生します。
したがって、ボックス化とボックス化解除はプログラムの速度とメモリ消費量に悪影響を与えるため、プログラムがボックス化/ボックス化解除操作を自動的に実行するタイミングに注意し、コードを記述するときにこのような状況を避けるようにしてください。
ボックス化を解除するときは、次の例外に注意してください。
1. 「ボックス化された値型インスタンスへの参照」を含む変数が null の場合、NullReferenceException がスローされます。
2. 参照が指すオブジェクトが期待される値型のボックス化されたインスタンスではない場合、InvalidCastException がスローされます。
たとえば、次のコード スニペット:

             Int32 x = 5;

            Object o = x;

            Int16 r = (Int16)o;//抛出InvalidCastException异常

これは、ボックス化を解除するときにのみ元のボックス化されていない値の型に変換できるためです。上記のコードを次のように変更します:

             Int32 x = 5;

            Object o = x;

            //Int16 r = (Int16)o;//抛出InvalidCastException异常

            Int16 r = (Int16)(Int32)o;

現時点では正しいです。

ボックス化解除後、次のコードに示すように、フィールドのコピーが行われます:

            //会发生字段复制
            Point p1;

            p1.x = 1;

            p1.y = 2;

            Object o = p1;//装箱,发生复制

            p1 = (Point)o;//拆箱,并将字段从已装箱的实例复制到栈中

次のコードセグメントを見てください:

            //要改变已装箱的值

            Point p2;

            p2.x = 10;

            p2.y = 20;

            Object o = p2;//装箱

            p2 = (Point)o;//拆箱

            p2.x = 40;//改变栈中变量的值

            o = p2;//再一次装箱,o引用新的已装箱实例

ここでの目的は、ボックス化後の p2 の x 値を 40 に変更することです。まず、ボックス化解除が 1 回実行され、フィールドのコピーがスタックに実行され、フィールドの値がスタック上で変更され、次にボックス化が実行されます。その時点で、新しいボックス化されたインスタンスがヒープ上に作成されます。 。このことから、ボックス化/ボックス化解除およびコピーがプログラムのパフォーマンスに与える影響もわかります。

さらにいくつかのボックス化とボックス化解除のコード スニペットを見てみましょう:

            //装箱拆箱演示
            Int32 v = 5;

            Object o = v;

            v = 123;

            Console.WriteLine(v + "," + (Int32)o);

ここでは 3 つのボックス化が発生していますが、Console.WriteLine でさらに 1 つのボックス化が発生していることがはっきりとわかります。ここの WriteLine には文字列型パラメータがあり、文字列が参照型であることは誰もが知っているため、ここでは (Int32)o をボックス化する必要があります。ここでも、プログラム内で文字列を接続するために + 記号を使用する問題について説明します。接続中に複数の値の型がある場合、いくつかのボックス化操作が実行されます。

ただし、上記のコードは変更できます:

            Object o = v;

            v = 123;

この方法では、ボックス化は行われません。
次のコードをもう一度見てください:

            //修改后
            Console.WriteLine(v.ToString() + "," + o);

ここでは 1 つのボックス化、つまり Object o = v のみが発生します。ただし、Console.WriteLine は int、bool、double などでオーバーロードされているため、ここではボックス化は発生しません。

上記はC#の基礎知識の内容です 基礎知識(18) 値型のボックス化とアンボックス化(1) その他の関連内容については、PHP中国語Webサイト(www.php.cn)に注目してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
如何使用C#编写时间序列预测算法如何使用C#编写时间序列预测算法Sep 19, 2023 pm 02:33 PM

如何使用C#编写时间序列预测算法时间序列预测是一种通过分析过去的数据来预测未来数据趋势的方法。它在很多领域,如金融、销售和天气预报中有广泛的应用。在本文中,我们将介绍如何使用C#编写时间序列预测算法,并附上具体的代码示例。数据准备在进行时间序列预测之前,首先需要准备好数据。一般来说,时间序列数据应该具有足够的长度,并且是按照时间顺序排列的。你可以从数据库或者

如何使用Redis和C#开发分布式事务功能如何使用Redis和C#开发分布式事务功能Sep 21, 2023 pm 02:55 PM

如何使用Redis和C#开发分布式事务功能引言分布式系统的开发中,事务处理是一项非常重要的功能。事务处理能够保证在分布式系统中的一系列操作要么全部成功,要么全部回滚。Redis是一种高性能的键值存储数据库,而C#是一种广泛应用于开发分布式系统的编程语言。本文将介绍如何使用Redis和C#来实现分布式事务功能,并提供具体代码示例。I.Redis事务Redis

如何实现C#中的人脸识别算法如何实现C#中的人脸识别算法Sep 19, 2023 am 08:57 AM

如何实现C#中的人脸识别算法人脸识别算法是计算机视觉领域中的一个重要研究方向,它可以用于识别和验证人脸,广泛应用于安全监控、人脸支付、人脸解锁等领域。在本文中,我们将介绍如何使用C#来实现人脸识别算法,并提供具体的代码示例。实现人脸识别算法的第一步是获取图像数据。在C#中,我们可以使用EmguCV库(OpenCV的C#封装)来处理图像。首先,我们需要在项目

C#开发中如何处理跨域请求和安全性问题C#开发中如何处理跨域请求和安全性问题Oct 08, 2023 pm 09:21 PM

C#开发中如何处理跨域请求和安全性问题在现代的网络应用开发中,跨域请求和安全性问题是开发人员经常面临的挑战。为了提供更好的用户体验和功能,应用程序经常需要与其他域或服务器进行交互。然而,浏览器的同源策略导致了这些跨域请求被阻止,因此需要采取一些措施来处理跨域请求。同时,为了保证数据的安全性,开发人员还需要考虑一些安全性问题。本文将探讨C#开发中如何处理跨域请

Redis在C#开发中的应用:如何实现高效的缓存更新Redis在C#开发中的应用:如何实现高效的缓存更新Jul 30, 2023 am 09:46 AM

Redis在C#开发中的应用:如何实现高效的缓存更新引言:在Web开发中,缓存是提高系统性能的常用手段之一。而Redis作为一款高性能的Key-Value存储系统,能够提供快速的缓存操作,为我们的应用带来了不少便利。本文将介绍如何在C#开发中使用Redis,实现高效的缓存更新。Redis的安装与配置在开始之前,我们需要先安装Redis并进行相应的配置。你可以

如何使用C#编写动态规划算法如何使用C#编写动态规划算法Sep 20, 2023 pm 04:03 PM

如何使用C#编写动态规划算法摘要:动态规划是求解最优化问题的一种常用算法,适用于多种场景。本文将介绍如何使用C#编写动态规划算法,并提供具体的代码示例。一、什么是动态规划算法动态规划(DynamicProgramming,简称DP)是一种用来求解具有重叠子问题和最优子结构性质的问题的算法思想。动态规划将问题分解成若干个子问题来求解,通过记录每个子问题的解,

如何实现C#中的遗传算法如何实现C#中的遗传算法Sep 19, 2023 pm 01:07 PM

如何在C#中实现遗传算法引言:遗传算法是一种模拟自然选择和基因遗传机制的优化算法,其主要思想是通过模拟生物进化的过程来搜索最优解。在计算机科学领域,遗传算法被广泛应用于优化问题的解决,例如机器学习、参数优化、组合优化等。本文将介绍如何在C#中实现遗传算法,并提供具体的代码示例。一、遗传算法的基本原理遗传算法通过使用编码表示解空间中的候选解,并利用选择、交叉和

如何使用C#编写背包问题算法如何使用C#编写背包问题算法Sep 19, 2023 am 09:21 AM

如何使用C#编写背包问题算法背包问题(KnapsackProblem)是一个经典的组合优化问题,它描述了一个给定容量的背包以及一系列物品,每个物品都有自己的价值和重量。目标是找到一种最佳策略,使得在不超过背包容量的情况下,装入背包的物品总价值最大。在C#中,可以通过动态规划方法来解决背包问题。具体实现如下:usingSystem;namespace

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。