一般型別系統中的實值型別

更新:2007 年 11 月

大部分的程式語言都提供內建資料型別,例如整數和浮點數值 (Floating-Point Number),當把它們當成引數傳遞時,它們的值會被複製,也就是傳值 (Passed by Value)。在 .NET Framework 中將這些資料型別稱為實值型別。Runtime 可支援兩種實值型別:

  • 內建實值型別

    .NET Framework 會定義內建實值型別 (例如 System.Int32System.Boolean),這些型別與程式語言所使用的基本資料型別對應且相同。

  • 使用者定義實值型別

    您使用的語言會提供您定義自己的實值型別的方式,這是從 System.ValueTypeSystem.Enum 衍生而來。如果您想要定義的型別代表很小的數值,例如複雜數值 (使用兩個浮點數值),可選擇將它定義為實值型別,因為傳值 (By Value) 方式可有效傳遞實值型別。如果您正在定義的型別以傳址 (By Reference) 方式傳遞更為有效,就應該將它定義為類別。

如需列舉型別的特定資訊,請參閱一般型別系統中的列舉型別

實值型別會被儲存成較有效率的基本型別,同時您仍可在型別上呼叫方法,包括在 System.ObjectSystem.ValueType 類別上定義的虛擬方法,以及在實值型別本身定義的任何方法。您可以建立實值型別的執行個體,將它們當做參數傳遞,並將它們當做區域變數儲存或將它們儲存到其他實值型別或物件的欄位中。實值型別沒有和儲存類別執行個體時關聯的過度耗用問題,而且不需要建構函式。

對每一個實值型別而言,Runtime 都提供了對應的 Boxed 型別,這是具有與實值型別相同狀態和行為的類別。需要 Boxed 型別時,有些語言會要求您使用特殊的語法;其他語言則會在需要時自動使用 Boxed 型別。當您定義實值型別時,會同時定義 Boxed 和 Unboxed 型別。

實值型別可以有欄位、屬性和事件,也可以有靜態和動態方法。當實值型別為 Boxed 時,會繼承 System.ValueType 的虛擬方法,而且可實作零或多個介面。

實值型別為密封型別,這表示無法從中衍生其他型別。但是,您可以直接在實值型別上定義虛擬方法,而且可以在 Boxed 或 Unboxed 格式的型別上呼叫這些方法。雖然您無法從實值型別衍生出其他型別,但是,如果在您所使用的語言中,使用虛擬方法比使用非虛擬或靜態方法來得方便,就可以在實值型別上定義虛擬方法。

下列範例顯示如何建構複雜實值的實值型別。

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

其他資源

一般型別系統