通用类型系统中的值类型

更新:2007 年 11 月

大多数编程语言提供内置的数据类型(比如整数和浮点数),这些数据类型会在作为参数传递时被复制(即,它们通过值来传递)。在 .NET Framework 中,这些称为值类型。运行库支持两种值类型:

  • 内置值类型

    .NET Framework 定义了内置值类型(例如 System.Int32System.Boolean),它们对应于编程语言使用的基元数据类型并与之相同。

  • 用户定义的值类型

    您的语言将提供多种方法来定义派生自 System.ValueTypeSystem.Enum 的您自己的值类型。如果您想定义一个表示小值的类型,比如复数(使用两个浮点数),则可以选择将其定义为值类型,因为您可以有效地通过值来传递值类型。如果您要定义的类型通过引用传递时会更高效,则应将其定义为类。

有关特定于枚举的信息,请参见通用类型系统中的枚举

值类型与基元类型有着同样的存储效率,然而您可以对它们调用方法,包括对 System.ObjectSystem.ValueType 类定义的虚方法,以及对值类型本身定义的任何方法。您可以创建值类型的实例,将它们作为参数传递,将它们存储为局部变量,或将它们存储在另一值类型或对象的字段中。值类型没有与存储类的实例相关的系统开销,并且它们不需要构造函数。

对于每一种值类型,运行库都提供一种相应的已装箱类型,这是与值类型有着相同状态和行为的类。当需要已装箱的类型时,某些语言要求使用特殊的语法;而另外一些语言会自动使用已装箱的类型。在定义值类型时,需要同时定义已装箱和未装箱的类型。

值类型可以有字段、属性和事件。它们也有静态和非静态方法。当它们被装箱时,会从 System.ValueType 继承虚方法,并可实现零个或更多接口。

值类型是密封的,这意味着不能从它们派生出其他类型。但是,可以直接对值类型定义虚方法,并且既可对该类型的已装箱形式,也可对未装箱形式调用这些方法。尽管不能从一种值类型派生出另一种类型,但是当所用语言处理虚方法比处理非虚方法或静态方法更方便时,可以对值类型定义虚方法。

下面的示例说明如何为复数构造值类型。

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

其他资源

通用类型系统