通用类型系统中的值类型
更新:2007 年 11 月
大多数编程语言提供内置的数据类型(比如整数和浮点数),这些数据类型会在作为参数传递时被复制(即,它们通过值来传递)。在 .NET Framework 中,这些称为值类型。运行库支持两种值类型:
内置值类型
.NET Framework 定义了内置值类型(例如 System.Int32 和 System.Boolean),它们对应于编程语言使用的基元数据类型并与之相同。
用户定义的值类型
您的语言将提供多种方法来定义派生自 System.ValueType 或 System.Enum 的您自己的值类型。如果您想定义一个表示小值的类型,比如复数(使用两个浮点数),则可以选择将其定义为值类型,因为您可以有效地通过值来传递值类型。如果您要定义的类型通过引用传递时会更高效,则应将其定义为类。
有关特定于枚举的信息,请参见通用类型系统中的枚举。
值类型与基元类型有着同样的存储效率,然而您可以对它们调用方法,包括对 System.Object 和 System.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)
请参见
概念
介绍 Visual Studio 中的 .NET Framework 类库