Типы значений в системе общих типов 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

Ссылки

Object

ValueType

Другие ресурсы

Система общих типов CTS