C#の型変換(キャスト)解説:(型名)の正しい使い方とデータ損失リスク

目次

C#における型変換の重要性

C#は静的型付け言語であり、変数はすべて厳密な型(intdoublestringなど)を持っています。原則として、異なる型同士の代入はできません。

しかし、プログラムのロジック上、ある型の値を別の型として扱いたい場合があります。例えば、int(整数)の値をlong(より大きな整数)として扱ったり、double(浮動小数点数)の値をint(整数)に変換したりする場合です。

このような場合に「型変換(Type Conversion)」が必要となります。この記事では、特にプログラマーが明示的に行う「キャスト」について、その方法と注意点を解説します。


2種類の型変換

C#の型変換は、大きく2種類に分類されます。

1. 暗黙的な型変換 (Implicit Conversion)

データが失われる危険性がない、安全な変換です。コンパイラが自動的に型を変換してくれます。

  • 例: 小さな型から大きな型への変換(intからlongへ、floatからdoubleへなど)
int currentScore = 5000;

// int (32ビット) から long (64ビット) への変換
// データ損失の心配がないため、自動的に行われる
long totalScore = currentScore; 

Console.WriteLine(totalScore); // 5000 が出力される

2. 明示的な型変換 (Explicit Conversion / キャスト)

データが失われる可能性がある変換です。コンパイラは自動では行わず、プログラマーが「データ損失の可能性を承知の上で変換する」という意思を明示する必要があります。

この明示的な変換を行う方法が「キャスト」であり、変換したい型の名前を括弧 () で囲んで値の前に記述します。

(変換したい型名) 値

明示的な型変換(キャスト)の具体例

キャストが必要となる主なケースは、「大きな型から小さな型へ」または「浮動小数点数から整数へ」の変換です。

例1: double から int へのキャスト (小数点以下の切り捨て)

double型(浮動小数点数)をint型(整数)にキャストすると、小数点以下の部分は四捨五入ではなく、すべて切り捨てられます

using System;

public class CastingExample
{
    public static void Main()
    {
        // 外部APIから取得した平均応答時間(秒)
        double averageResponseTime = 3.85;

        // (int) でキャストすると、小数点以下 (0.85) が切り捨てられる
        int responseTimeInt = (int)averageResponseTime;

        Console.WriteLine($"元の値 (double): {averageResponseTime}"); // 3.85
        Console.WriteLine($"キャスト後の値 (int): {responseTimeInt}"); // 3
    }
}

例2: decimal から int へのキャスト (小数点以下の切り捨て)

高精度なdecimal型(金融計算などで使用)をintにキャストする場合も同様に、小数点以下が切り捨てられます。

using System;

public class DecimalCastExample
{
    public static void Main()
    {
        decimal totalAmount = 12800.90m;
        
        // (int) でキャスト
        int amountIntegerPart = (int)totalAmount;

        Console.WriteLine($"元の値 (decimal): {totalAmount}"); // 12800.90
        Console.WriteLine($"キャスト後の値 (int): {amountIntegerPart}"); // 12800
    }
}

例3: long から int へのキャスト (桁あふれ/オーバーフローのリスク)

大きな型(long)を小さな型(int)にキャストする場合、元の値が小さな型の許容範囲(intの場合は約±21億)を超えていると、「桁あふれ(オーバーフロー)」が発生し、値がまったく異なる(通常は負の)数値になってしまいます。

using System;

public class OverflowExample
{
    public static void Main()
    {
        // int の最大値 (約21億) を超える long の値
        long largeTransactionId = 3_000_000_000L; // 30億

        // (int) で明示的にキャスト
        // int の範囲を超えるため、オーバーフローが発生する
        int legacyId = (int)largeTransactionId;

        Console.WriteLine($"元の値 (long): {largeTransactionId}"); // 3000000000
        Console.WriteLine($"キャスト後の値 (int): {legacyId}"); // -1294967296 (環境により異なる可能性あり)
    }
}

このように、キャストは非常に危険な操作になる可能性があります。intの範囲を超える可能性があるlongの値をintにキャストするのは、原則として避けるべきです。


補足: キャストと Convert クラスの違い

doubleintに変換する方法として、キャスト (int) 以外に Convert.ToInt32() があります。この2つは丸め処理の動作が異なります

  • キャスト (int)value: 常に切り捨て(0方向に丸め)ます。
    • (int)3.83
    • (int)3.23
    • (int)-3.8-3
  • Convert.ToInt32(value): 最近接偶数への丸め(銀行家の丸め)を行います。
    • Convert.ToInt32(3.8)4 (4に近い)
    • Convert.ToInt32(3.2)3 (3に近い)
    • Convert.ToInt32(3.5)4 (3と4の中間だが、偶数の4が選ばれる)
    • Convert.ToInt32(4.5)4 (4と5の中間だが、偶数の4が選ばれる)

どちらの動作を期待しているかによって、適切な変換方法を選択する必要があります。


まとめ

明示的な型変換(キャスト)は、異なる型同士でデータを移し替えるための構文です。

(型名) を記述することで、コンパイラに対して強制的に型変換を指示しますが、それに伴い「小数点以下の切り捨て」や「桁あふれ(オーバーフロー)」といったデータ損失が発生するリスクを伴います。

キャストを使用する際は、変換によってデータがどのように変化するかを正確に理解し、意図しないデータ損失やバグが発生しないよう注意深く使用する必要があります。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次