C# Academy · レッスン

ボックス化とボックス化解除

objectへの変換にかかるコストを理解します。

レッスン 2/413 ステップ

「ボックス化とボックス化解除」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

ボックス化とは

ボックス化とは、値型をオブジェクトの中にラップし、参照型として扱えるようにすることです。object o = 5;では、int がヒープ上でボックス化されます。

using System;

class Program
{
    static void Main()
    {
        int n = 5;
        object o = n;   // boxing
        Console.WriteLine("Boxed value: " + o);
    }
}

ボックス化が起きる理由

値型をobject型(またはインターフェイス型)の変数に代入すると、必ずボックス化が起きます。ランタイムは、値のコピーを保持するボックスをヒープ上に確保します。

using System;

class Program
{
    static void Main()
    {
        double d = 3.14;
        object boxed = d;   // boxing copies d into a heap object
        Console.WriteLine(boxed);
    }
}

ボックス化解除とは

ボックス化解除とは、明示的なキャストによってボックスから値型を取り出すことです。キャストする型は、ボックス化された型と完全に一致していなければなりません。

using System;

class Program
{
    static void Main()
    {
        object o = 42;        // boxing
        int n = (int)o;        // unboxing
        Console.WriteLine("Unboxed: " + n);
    }
}

ボックス化解除には正しい型が必要

ボックス化解除では、元の型と完全に同じ型を指定する必要があります。異なる型へのボックス化解除を行うと、InvalidCastExceptionがスローされます。

using System;

class Program
{
    static void Main()
    {
        object o = 100;
        try
        {
            long wrong = (long)o;   // InvalidCastException at runtime
            Console.WriteLine(wrong);
        }
        catch (InvalidCastException)
        {
            Console.WriteLine("Must unbox to int, not long");
        }
    }
}

ボックス化ではコピーが作られる

ボックス化では値がコピーされます。その後で元の値を変更しても、ボックス内のコピーは変わりません。

using System;

class Program
{
    static void Main()
    {
        int n = 1;
        object o = n;   // box copies 1
        n = 99;
        Console.WriteLine("original=" + n + ", boxed=" + o);
    }
}

ボックス化のコスト

ボックス化のたびにヒープメモリが確保され、ガベージコレクションの負荷が増加します。頻繁に実行されるループでは、このオーバーヘッドによってパフォーマンスが大きく低下することがあります。

using System;

class Program
{
    static void Main()
    {
        // Each iteration boxes an int -> many heap allocations
        object sumBox = 0;
        for (int i = 0; i < 5; i++)
        {
            int current = (int)sumBox + i;
            sumBox = current;   // box again
        }
        Console.WriteLine("Result: " + sumBox);
    }
}

ジェネリックによるボックス化の回避

List<int>のようなジェネリックコレクションは、古い非ジェネリックのArrayListとは異なり、値型をボックス化せずに格納します。

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var list = new List<int>();   // no boxing
        list.Add(1);
        list.Add(2);
        int first = list[0];           // no unboxing
        Console.WriteLine("First: " + first);
    }
}

インターフェイスでのボックス化

構造体をインターフェイス型の変数に代入してもボックス化が起きます。これは、インターフェイスの参照がヒープ上のオブジェクトを指す必要があるためです。

using System;

class Program
{
    static void Main()
    {
        int n = 7;
        IComparable c = n;   // boxing to interface
        Console.WriteLine(c.CompareTo(10));
    }
}

ボックス化された型の判定

ボックス化解除を安全に行う前に、isを使って実行時にボックス化されたオブジェクトの型を確認できます。

using System;

class Program
{
    static void Main()
    {
        object o = 3.5;
        if (o is double d)
            Console.WriteLine("It is a double: " + d);
        else
            Console.WriteLine("Not a double");
    }
}

文字列連結でのボックス化

値型を文字列と連結すると、ボックス化されることがあります。文字列補間や ToString を使うほうが明確な場合が多いですが、ここでのボックス化は通常、無視できる程度です。

using System;

class Program
{
    static void Main()
    {
        int count = 3;
        string msg = "Count is " + count;   // count is converted
        Console.WriteLine(msg);
    }
}

まとめ

ボックス化は値型と参照型の世界を橋渡ししますが、メモリ確保のコストがかかります。ボックス化を避けるにはジェネリックを優先し、安全性を確認したうえで元の型と完全に同じ型へボックス化解除してください。

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        object boxed = 256;
        if (boxed is int value)
            Console.WriteLine("Safely unboxed: " + value);

        var noBox = new List<int> { 1, 2, 3 };
        Console.WriteLine("Generic count: " + noBox.Count);
    }
}

確認問題

ボックス化とボックス化解除についての理解度を確認しましょう。

要点の復習

ボックス化は値型をヒープ上のオブジェクトでラップすることです(例:object o = 5;)。ボックス化解除では、元の型と完全に同じ型への明示的なキャストによって値を取り出します。ボックス化では値のコピーとメモリ確保が行われるため、GC の負荷が増加します。ボックス化を避けるにはList<int>のようなジェネリックコレクションを優先し、安全なボックス化解除にはisを使います。

using System;

class Program
{
    static void Main()
    {
        object boxed = 42;     // box
        int n = (int)boxed;     // unbox
        Console.WriteLine(n);
    }
}
無料で開始

AI チューターと学ぶ C# — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
93
レッスン
346

よくある質問

「ボックス化とボックス化解除」レッスンは無料ですか?

はい。「ボックス化とボックス化解除」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「ボックス化とボックス化解除」で何を学びますか?

objectへの変換にかかるコストを理解します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「ボックス化とボックス化解除」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 値型と参照型
  2. ボックス化とボックス化解除
  3. 暗黙的変換と明示的変換
  4. Convertクラスと解析
← C# Academyに戻る