C# Academy · leksjon

Brukerdefinerte konverteringer

Legg til implisitte og eksplisitte konverteringsoperatorer.

Leksjon 3 av 413 trinn

Brukerdefinerte konverteringer er en gratis leksjon i C# Academy på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i C# Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i C# Academy inneholder totalt 4 leksjoner.

Brukerdefinerte konverteringer

C# lar en type definere hvordan den konverteres til eller fra en annen type ved hjelp av operatorene implicit og explicit. Implisitte konverteringer skjer automatisk; eksplisitte konverteringer krever en cast.

En implicit-konvertering

Bruk implicit operator når en konvertering alltid er trygg og tapsfri. Kompilatoren bruker den automatisk overalt der 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 explicit-konvertering

Bruk explicit operator når en konvertering kan føre til tap av informasjon eller mislykkes. Kallere må skrive en cast, som signaliserer at de aksepterer 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);
    }
}

Konvertere til din type

Konverteringer kan også gå den andre veien: fra en annen type til din type. Her bygger en implicit-operator en Celsius 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);
    }
}

Implisitt eller eksplisitt: Valg

Tommelfingerregelen er: Gjør konverteringen implisitt bare hvis den aldri mister data og aldri gir feil. Hvis den kan miste presisjon, gi overflow eller mislykkes, bør den være eksplisitt.

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 mellom egendefinerte typer

Konverteringer er ikke begrenset til innebygde typer. De kan også brukes mellom to av dine egne typer, for eksempel fra polare 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 kan brukes med operatorer

Når en konvertering finnes, kan verdien brukes i uttrykk for måltypen. En implisitt konvertering til double gjør at typen din kan brukes direkte i aritmetikk.

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);
    }
}

Unngå overraskende implisitte konverteringer

Implisitte konverteringer som ikke åpenbart er trygge, kan skjule feil fordi kompilatoren bruker dem uten å si fra. Når du er i tvil, bør du foretrekke eksplisitte konverteringer slik at hensikten 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

I likhet med andre operatorer er konverteringsoperatorer public static. Nøyaktig én av de involverte typene må være typen som deklarerer 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 spesielt nyttige for tynne wrapper-typer som styrker typesystemet uten å skape unødvendig friksjon. Her konverteres en NonEmptyString implisitt til string, men det kreves en eksplisitt cast for å opprette 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

Definer en wrapper med en implisitt konvertering ut (trygg) og en eksplisitt konvertering inn (validert). Legg merke til hvilken retning som krever en cast.

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 + "%");
    }
}

Hurtigsjekk

Velg riktig type konvertering.

Oppsummering

Brukerdefinerte konverteringer gjør at typene dine kan samhandle på en ryddig måte.

  • implicit operator for konverteringer som alltid er trygge og ikke mister data.
  • explicit operator når data kan gå tapt eller konverteringen kan mislykkes.
  • Konverteringer kan gå til innebygde eller egendefinerte typer, i begge retninger.
  • De er public static og deklareres av én av de involverte typene.
Gratis å komme i gang

Lær deg C# med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
93
Leksjoner
346

Ofte stilte spørsmål

Er leksjonen «Brukerdefinerte konverteringer» gratis?

Ja – hele teksten i «Brukerdefinerte konverteringer» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av C# Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i C# Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Brukerdefinerte konverteringer»?

Legg til implisitte og eksplisitte konverteringsoperatorer. Du øver på C# Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med C# Academy?

Ingen tidligere erfaring er nødvendig. C# Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Brukerdefinerte konverteringer»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne C# Academy-leksjonen?

Ja. Alle C# Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Overbelaste aritmetiske operatorer
  2. Overbelaste sammenligningsoperatorer
  3. Brukerdefinerte konverteringer
  4. Beste praksis for operatoroverbelastning
← Tilbake til C# Academy