Freigeben über


Werttypen

Die meisten Programmiersprachen bieten integrierte Datentypen, wie ganze Zahlen und Gleitkommazahlen, die bei ihrer Übergabe als Argumente kopiert werden (d. h., sie werden als Wert übergeben). In .NET Framework werden diese Typen als Werttypen bezeichnet. Die Laufzeit unterstützt zwei Arten von Werttypen:

  • Integrierte Werttypen

    In .NET Framework werden integrierte Werttypen definiert, z. B. System.Int32 und System.Boolean. Diese entsprechen den von Programmiersprachen verwendeten primitiven Datentypen und sind mit ihnen identisch.

  • Benutzerdefinierte Werttypen

    Ihre Programmiersprache bietet Möglichkeiten, eigene Werttypen zu definieren, die von System.ValueType abgeleitet werden. Wenn Sie einen Typ zur Darstellung eines kleinen Wertes definieren möchten, z. B. einer komplexen Zahl (in der zwei Gleitkommazahlen verwendet werden), können Sie den Typ beispielsweise als Werttyp definieren, da er effizient als Wert übergeben werden kann. Falls der definierte Typ effizienter als Verweis übergeben werden könnte, sollten Sie ihn stattdessen als Klasse definieren.

Werttypen werden genauso effektiv wie primitive Typen gespeichert. Für Werttypen können jedoch darüber hinaus Methoden aufgerufen werden, darunter die in den Klassen System.Object und System.ValueType definierten virtuellen Methoden sowie alle für den Werttyp selbst definierten Methoden. Sie können Instanzen von Werttypen erstellen, diese als Parameter übergeben, als lokale Variablen speichern oder im Feld eines anderen Werttyps oder Objekts speichern. Ihre Verarbeitung ist weniger aufwendig, da keine Instanz einer Klasse gespeichert werden muss und sie keine Konstruktoren erfordern.

Die Common Language Runtime stellt für jeden Werttyp einen entsprechenden geschachtelten Werttyp bereit, der eine Klasse darstellt, die denselben Zustand und dasselbe Verhalten wie der Werttyp aufweist. In einigen Sprachen muss eine spezielle Syntax verwendet werden, wenn ein mittels Boxing gepackter Typ erforderlich ist; in anderen Sprachen wird der mittels Boxing gepackte Typ bei Bedarf automatisch verwendet. Die Definition eines Werttyps schließt sowohl den mittels Boxing gepackten als auch den mittels Unboxing entpackten Typ ein.

Werttypen können über Felder, Eigenschaften und Ereignisse sowie über statische und nicht statische Methoden verfügen. Mittels Boxing gepackte Werttypen erben virtuelle Methoden von System.ValueType und können keine oder mehrere Schnittstellen implementieren.

Werttypen sind versiegelt, was bedeutet, dass kein anderer Typ von ihnen abgeleitet werden kann. Sie können virtuelle Methoden jedoch direkt für den Werttyp definieren, und diese Methoden können entweder für die mittels Boxing gepackte oder die mittels Unboxing entpackte Form des Typs aufgerufen werden. Obwohl die Ableitung eines anderen Typs von einem Werttyp nicht möglich ist, können Sie bei Verwendung einer Sprache, in der virtuelle Methoden die bequemere Alternative zu nicht virtuellen oder statischen Methoden darstellen, virtuelle Methoden für einen Werttyp definieren.

Das folgende Beispiel veranschaulicht, wie Sie einen Werttyp für komplexe Zahlen erstellen.

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
[C#]
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);
    }
}

Dieses Programm gibt folgendes Ergebnis aus:

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)

Siehe auch

Allgemeines Typensystem | Einführung in die .NET Framework-Klassenbibliothek | Klassen | System.Object | System.ValueType