共通型システムの値型

更新 : 2007 年 11 月

ほとんどのプログラミング言語は、引数として渡されるときにコピーされる (つまり、値渡しされる)、整数や浮動小数点数などの組み込みのデータ型を提供しています。.NET Framework では、このようなデータ型を値型と呼びます。ランタイムは、次の 2 種類の値型をサポートしています。

  • 組み込みの値型

    .NET Framework は、System.Int32System.Boolean などの組み込みの値型を定義しており、これらの値型は、各種プログラミング言語で使用されるプリミティブ データ型に対応し、同じ機能を果たします。

  • ユーザー定義の値型

    各言語で、System.ValueType または System.Enum から派生する独自の値型を定義できます。複素数 (2 つの浮動小数点数を使用する数) などの小さな値を表す型を定義する場合は、値型だと効率的に値渡しできるため、その値を値型として定義できます。参照渡しの方が効率的な型を定義する場合は、値型ではなくクラスとして定義する必要があります。

列挙型の詳細については、「共通型システムの列挙型」を参照してください。

値型はプリミティブ型と同じくらい効率的に格納されます。それでも、値型に対しては、System.Object クラスと System.ValueType クラスに定義されている仮想メソッドや、その値型自体に定義されているメソッドを呼び出すことができます。値型はインスタンス化する、パラメータとして渡す、ローカル変数として格納する、または別の値型またはオブジェクトのフィールドに格納することができます。値型には、クラスのインスタンスを格納することによるオーバーヘッドがなく、コンストラクタも必要ありません。

ランタイムはそれぞれの値型に対応する、ボックス化された型を提供しています。ボックス化された型とは、値型と同じ状態および動作を備えたクラスのことです。言語によっては、ボックス化された型が必要なときに特別な構文を使用する必要がありますが、ボックス化された型を必要に応じて自動的に使用できる言語もあります。値型を定義するときには、ボックス化された型とボックス化解除された型の両方を定義します。

値型には、フィールド、プロパティ、およびイベントを関連付けることができます。また、値型は静的メソッドと非静的メソッドを持つこともできます。値型がボックス化されると、その型は System.ValueType から仮想メソッドを継承し、0 個以上のインターフェイスを実装できるようになります。

値型には、その型から派生する型を作成できないことを示す sealed 属性が適用されます。しかし、値型に仮想メソッドを直接定義することができ、それらの仮想メソッドを、その値型をボックス化した型またはボックス化解除した型のいずれかに対して呼び出すことができます。値型から他の型を派生させることはできませんが、非仮想メソッドや静的メソッドよりも仮想メソッドを使用した方が便利な言語を使用している場合は、値型に仮想メソッドを定義できます。

複素数の値型を生成する方法を次の例に示します。

Option Strict
Option Explicit

Imports System

' Value type definition for a complex number representation.
Public Structure Complex
    Public r, i As Double
    
    ' Constructor.
    Public Sub New(r As Double, i As Double)
        Me.r = r
        Me.i = i
    End Sub
    
    ' Returns one divided by the current value.
    Public ReadOnly Property Reciprocal() As Complex
        Get
            If r = 0.0 And i = 0.0 Then
                Throw New DivideByZeroException()
            End If 
            Dim div As Double = r * r + i * i
            Return New Complex(r / div, -i / div)
        End Get
    End Property
    
    
    ' Conversion methods.
    Public Shared Function ToDouble(a As Complex) As Double
        Return a.r
    End Function

    Public Shared Function ToComplex(r As Double) As Complex
        Return New Complex(r, 0.0)
    End Function

    ' Basic unary methods.
    Public Shared Function ToPositive(a As Complex) As Complex
        Return a
    End Function

    Public Shared Function ToNegative(a As Complex) As Complex
        Return New Complex(-a.r, -a.i)
    End Function

    ' Basic binary methods for addition, subtraction, multiplication, and division.
    Public Shared Function Add(a As Complex, b As Complex) As Complex
        Return New Complex(a.r + b.r, a.i + b.i)
    End Function

    Public Shared Function Subtract(a As Complex, b As Complex) As Complex
        Return New Complex(a.r - b.r, a.i - b.i)
    End Function

    Public Shared Function Multiply(a As Complex, b As Complex) As Complex
        Return New Complex(a.r * b.r - a.i * b.i, a.r * b.i + a.i * b.r)
    End Function

    Public Shared Function Divide(a As Complex, b As Complex) As Complex
        Return Multiply(a, b.Reciprocal)
    End Function

    ' Override the ToString method so the value appears in write statements.
    Public Overrides Function ToString As String
        Return String.Format("({0}+{1}i)", r, i)
    End Function
End Structure

' Entry point.
Public Class ValueTypeSample
    
    Public Shared Sub Main()
        Dim a As New Complex(0, 1)
        Dim b As New Complex(0, - 2)
        
        Console.WriteLine()
        Console.WriteLine("a = " & a.ToString)
        Console.WriteLine("b = " & b.ToString)
        
        Console.WriteLine()
        Console.WriteLine("a + b = " & Complex.Add(a, b).ToString)
        Console.WriteLine("a - b = " & Complex.Subtract(a, b).ToString)
        Console.WriteLine("a * b = " & Complex.Multiply(a, b).ToString)
        Console.WriteLine("a / b = " & Complex.Divide(a, b).ToString)
        
        Console.WriteLine()
        Console.WriteLine("(double)a = " & Complex.ToDouble(a).ToString)
        Console.WriteLine("(Complex)5 = " & Complex.ToComplex(5).ToString)
    End Sub
End Class
using System;

// Value type definition for a complex number representation.
public struct Complex
{
    public double r, i;

    // Constructor.
    public Complex(double r, double i) { this.r = r; this.i = i; }

    // Returns one divided by the current value.
    public Complex Reciprocal
    {
        get
        {
            if (r == 0d && i == 0d)
                throw new DivideByZeroException();

            double div = r*r + i*i;
            return new Complex(r/div, -i/div);
        }
    }

    // Conversion operators.
    public static explicit operator double(Complex a)
    {
        return a.r;
    }
    public static implicit operator Complex(double r)
    {
        return new Complex(r,0d);
    }

    // Basic unary operators.
    public static Complex operator + (Complex a)
    {
        return a;
    }
    public static Complex operator - (Complex a)
    {
        return new Complex(-a.r, -a.i);
    }

    // Basic binary operators for addition, subtraction, multiplication, and division.
    public static Complex operator + (Complex a, Complex b)
    {
        return new Complex(a.r + b.r, a.i + b.i);
    }
    public static Complex operator - (Complex a, Complex b)
    {
        return new Complex(a.r - b.r, a.i - b.i);
    }
    public static Complex operator * (Complex a, Complex b)
    {
        return new Complex(a.r*b.r - a.i*b.i, a.r*b.i + a.i*b.r);
    }
    public static Complex operator / (Complex a, Complex b)
    {
        return a * b.Reciprocal;
    }

    // Override the ToString method so the value appears in write statements.
    public override string ToString() {
        return String.Format("({0}+{1}i)", r, i);
    }
}

// Entry point.
public class ValueTypeSample
{
    public static void Main()
    {
        Complex a = new Complex(0, 1);
        Complex b = new Complex(0, -2);

        Console.WriteLine();
        Console.WriteLine("a = " + a);
        Console.WriteLine("b = " + b);

        Console.WriteLine();
        Console.WriteLine("a + b = " + (a+b));
        Console.WriteLine("a - b = " + (a-b));
        Console.WriteLine("a * b = " + (a*b));
        Console.WriteLine("a / b = " + (a/b));

        Console.WriteLine();
        Console.WriteLine("(double)a = " + (double)a);
        Console.WriteLine("(Complex)5 = " + (Complex)5);
    }
}

このプログラムによって、次のような出力が生成されます。

a = (0+1i)
b = (0+-2i)

a + b = (0+-1i)
a - b = (0+3i)
a * b = (2+0i)
a / b = (-0.5+0i)

(double)a = 0
(Complex)5 = (5+0i)

参照

概念

.NET Framework クラス ライブラリの概要

Visual Studio の .NET Framework クラス ライブラリの概要

共通型システムの列挙型

参照

Object

ValueType

その他の技術情報

共通型システム