Типы значений в системе общих типов CTS
Обновлен: Ноябрь 2007
Большинство языков программирования предоставляют встроенные типы данных, например целые числа или числа с плавающей запятой, которые копируются при передаче в качестве аргументов (передаче по значению). В платформе .NET Framework такие типы называются типами значений. В среде выполнения поддерживается два вида типов значений.
Встроенные типы значений
В платформе .NET Framework определены встроенные типы значений, например System.Int32 и System.Boolean, которые соответствуют и идентичны простым типам данных, используемым языками программирования.
Пользовательские типы значений
Используемый язык программирования предоставляет способы определения собственных типов значений, которые являются производными от System.ValueType или System.Enum. Если нужно определить тип, представляющий малое значение, например, комплексное число (используя два числа с плавающей запятой), то его можно определить в виде типа значений, поскольку такой тип значения можно эффективно передавать по значению. Если определяемый тип более эффективно передавать по ссылке, его следует определить в виде класса.
Сведения, относящиеся к перечислениям, см. в разделе Перечисления в системе общих типов CTS.
Типы значений хранятся так же эффективно, как и простые типы, только для них еще можно вызывать методы, включая виртуальные методы, определенные в классах 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)
См. также
Основные понятия
Общие сведения о библиотеке классов .NET Framework
Знакомство с библиотекой классов .NET Framework в Visual Studio
Перечисления в системе общих типов CTS