C# Academy · Lektion

Brugerdefinerede konverteringer

Tilføj implicitte og eksplicitte konverteringsoperatorer.

Lektion 3 af 413 trin

Brugerdefinerede konverteringer er en gratis C# Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C# Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C# Academy-kurset indeholder 4 lektioner i alt.

Brugerdefinerede konverteringer

C# lader en type definere, hvordan den konverterer til eller fra en anden type ved hjælp af operatorerne implicit og explicit. Implicitte konverteringer sker automatisk; eksplicitte kræver en typekonvertering.

En implicit konvertering

Brug implicit operator, når en konvertering altid er sikker og uden datatab. Kompilatoren anvender den automatisk overalt, hvor måltypen forventes.

using System;

public struct Celsius
{
    public double Degrees;
    public Celsius(double d) { Degrees = d; }

    // Always safe: a Celsius is just a number
    public static implicit operator double(Celsius c) => c.Degrees;
}

public class Program
{
    public static void Main()
    {
        Celsius temp = new Celsius(21.5);
        double d = temp; // implicit, no cast needed
        Console.WriteLine(d);
    }
}

En eksplicit konvertering

Brug explicit operator, når en konvertering kan medføre datatab eller mislykkes. Den, der kalder koden, skal skrive en typekonvertering, hvilket signalerer, at vedkommende accepterer risikoen.

using System;

public struct Money
{
    public decimal Amount;
    public Money(decimal a) { Amount = a; }

    // Loses the fractional cents, so make it explicit
    public static explicit operator int(Money m) => (int)m.Amount;
}

public class Program
{
    public static void Main()
    {
        var m = new Money(19.99m);
        int dollars = (int)m; // explicit cast required
        Console.WriteLine(dollars);
    }
}

Konvertering til din type

Konverteringer kan også gå den anden vej: fra en anden type til din type. Her opretter en implicit-operator en Celsius ud fra en rå double.

using System;

public struct Celsius
{
    public double Degrees;
    public Celsius(double d) { Degrees = d; }

    public static implicit operator Celsius(double d) => new Celsius(d);

    public override string ToString() => Degrees + "C";
}

public class Program
{
    public static void Main()
    {
        Celsius t = 18.0; // double implicitly becomes Celsius
        Console.WriteLine(t);
    }
}

Implicit eller eksplicit: Sådan vælger du

Tommelfingerreglen er: Gør konverteringen implicit, hvis den aldrig mister data og aldrig udløser en fejl. Hvis den kan miste præcision, give overflow eller mislykkes, skal den være eksplicit.

using System;

public struct Percentage
{
    public double Value; // 0..1
    public Percentage(double v) { Value = v; }

    // Safe and lossless -> implicit
    public static implicit operator double(Percentage p) => p.Value;
    // Could be out of range -> explicit
    public static explicit operator Percentage(double v) => new Percentage(v);
}

public class Program
{
    public static void Main()
    {
        double d = new Percentage(0.25);
        var p = (Percentage)0.5;
        Console.WriteLine(d + " " + p.Value);
    }
}

Konverteringer mellem brugerdefinerede typer

Konverteringer er ikke begrænset til indbyggede typer. Du kan konvertere mellem to af dine egne typer, for eksempel fra polære til kartesiske koordinater.

using System;

public struct Cartesian
{
    public double X, Y;
    public Cartesian(double x, double y) { X = x; Y = y; }
    public override string ToString() => "(" + Math.Round(X, 2) + ", " + Math.Round(Y, 2) + ")";
}

public struct Polar
{
    public double R, Theta;
    public Polar(double r, double theta) { R = r; Theta = theta; }
    public static explicit operator Cartesian(Polar p)
        => new Cartesian(p.R * Math.Cos(p.Theta), p.R * Math.Sin(p.Theta));
}

public class Program
{
    public static void Main()
    {
        var c = (Cartesian)new Polar(1.0, 0.0);
        Console.WriteLine(c);
    }
}

Konverteringer fungerer sammen med operatorer

Når der findes en konvertering, kan værdien indgå i udtryk for måltypen. En implicit konvertering til double gør det muligt at bruge din type direkte i aritmetiske beregninger.

using System;

public struct Meters
{
    public double Value;
    public Meters(double v) { Value = v; }
    public static implicit operator double(Meters m) => m.Value;
}

public class Program
{
    public static void Main()
    {
        var distance = new Meters(5);
        double doubled = distance * 2; // uses implicit conversion to double
        Console.WriteLine(doubled);
    }
}

Undgå overraskende implicitte konverteringer

Implicitte konverteringer, der ikke tydeligvis er sikre, kan skjule fejl, fordi compileren anvender dem lydløst. Hvis du er i tvivl, så vælg en eksplicit konvertering, så hensigten er synlig i koden.

using System;

public struct UserId
{
    public int Value;
    public UserId(int v) { Value = v; }
    // Explicit on purpose: an int is not always a valid id
    public static explicit operator UserId(int v) => new UserId(v);
    public static explicit operator int(UserId id) => id.Value;
}

public class Program
{
    public static void Main()
    {
        var id = (UserId)42;
        int raw = (int)id;
        Console.WriteLine(raw);
    }
}

Konverteringsoperatorer er static

Ligesom andre operatorer er konverteringsoperatorer public static. Præcis én af de involverede typer skal være den type, der erklærer operatoren.

using System;

public struct Fahrenheit
{
    public double Degrees;
    public Fahrenheit(double d) { Degrees = d; }
    public static implicit operator Fahrenheit(double d) => new Fahrenheit(d);
    public static implicit operator double(Fahrenheit f) => f.Degrees;
    public override string ToString() => Degrees + "F";
}

public class Program
{
    public static void Main()
    {
        Fahrenheit f = 98.6;
        double d = f;
        Console.WriteLine(f + " = " + d);
    }
}

En praktisk wrapper-type

Konverteringer er særligt nyttige for tynde wrapper-typer, der styrker typesystemet uden at gøre brugen besværlig. Her konverteres en NonEmptyString implicit til string, men det kræver en eksplicit konvertering at oprette den.

using System;

public struct NonEmptyString
{
    public string Value;
    public NonEmptyString(string v)
    {
        if (string.IsNullOrEmpty(v)) throw new ArgumentException("empty");
        Value = v;
    }
    public static explicit operator NonEmptyString(string s) => new NonEmptyString(s);
    public static implicit operator string(NonEmptyString s) => s.Value;
}

public class Program
{
    public static void Main()
    {
        var name = (NonEmptyString)"Ada";
        string s = name;
        Console.WriteLine(s);
    }
}

Prøv selv

Definér en wrapper med en implicit konvertering udad, som er sikker, og en eksplicit konvertering indad, som validerer værdien. Bemærk, hvilken retning der kræver en konvertering.

using System;

public struct Ratio
{
    public double Value;
    public Ratio(double v)
    {
        if (v < 0 || v > 1) throw new ArgumentOutOfRangeException(nameof(v));
        Value = v;
    }
    public static implicit operator double(Ratio r) => r.Value; // always safe
    public static explicit operator Ratio(double v) => new Ratio(v); // may throw
}

public class Program
{
    public static void Main()
    {
        var half = (Ratio)0.5;   // explicit, validated
        double d = half;          // implicit, safe
        Console.WriteLine(d * 100 + "%");
    }
}

Hurtigt tjek

Vælg den rigtige type konvertering.

Opsummering

Brugerdefinerede konverteringer gør det nemt for dine typer at fungere sammen.

  • implicit operator bruges til konverteringer, der altid er sikre og ikke mister data.
  • explicit operator bruges, når data kan gå tabt, eller konverteringen kan mislykkes.
  • Konverteringer kan gå til indbyggede eller brugerdefinerede typer i begge retninger.
  • De er public static og erklæres af en af de involverede typer.
Gratis at komme i gang

Lær C# med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
93
Lektioner
346

Ofte stillede spørgsmål

Er lektionen “Brugerdefinerede konverteringer” gratis?

Ja — hele teksten til “Brugerdefinerede konverteringer” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C# Academy-kurset, skal du opgradere til CoddyKit PRO. C# Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Brugerdefinerede konverteringer”?

Tilføj implicitte og eksplicitte konverteringsoperatorer. Du øver dig i C# Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på C# Academy?

Der kræves ingen tidligere erfaring. C# Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Brugerdefinerede konverteringer”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne C# Academy-lektion?

Ja. Alle C# Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Overload af aritmetiske operatorer
  2. Overload af sammenligningsoperatorer
  3. Brugerdefinerede konverteringer
  4. Best practices for operator-overload
← Tilbage til C# Academy