C# Academy · Lektion

Användardefinierade konverteringar

Lägg till implicita och explicita konverteringsoperatorer.

Lektion 3 av 413 steg

Användardefinierade konverteringar är en gratis lektion i C# Academy på CoddyKit. Detta är lektion 3 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för C# Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i C# Academy innehåller totalt 4 lektioner.

Användardefinierade konverteringar

C# låter en typ definiera hur den konverteras till eller från en annan typ med operatorerna implicit och explicit. Implicita konverteringar sker automatiskt, medan explicita konverteringar kräver en typkonvertering.

En implicit konvertering

Använd implicit operator när en konvertering alltid är säker och inte medför informationsförlust. Kompilatorn tillämpar den automatiskt överallt där måltypen förväntas.

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

Använd explicit operator när en konvertering kan medföra informationsförlust eller misslyckas. Den som anropar koden måste skriva en typkonvertering, vilket signalerar att risken accepteras.

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

Konvertera till er typ

Konverteringar kan även gå åt andra hållet: från en annan typ till er typ. Här skapar en implicit-operator en Celsius från 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 kontra explicit: välja

Tumregeln är: gör den implicit endast om den aldrig förlorar data och aldrig kastar ett undantag. Om den kan förlora precision, orsaka spill eller misslyckas ska den vara explicit.

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

Omvandlingar mellan egna typer

Omvandlingar är inte begränsade till inbyggda typer. Du kan omvandla mellan två egna typer, till exempel från polära till kartesiska 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);
    }
}

Omvandlingar samverkar med operatorer

När en omvandling väl finns kan värdet ingå i uttryck för måltypen. En implicit omvandling till double gör att typen kan användas direkt i aritmetiska uttryck.

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

Undvik överraskande implicita omvandlingar

Implicita omvandlingar som inte är uppenbart säkra kan dölja buggar, eftersom kompilatorn tillämpar dem i tysthet. När du är osäker bör du föredra explicit, så att avsikten syns 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);
    }
}

Omvandlingsoperatorer är static

Precis som andra operatorer är omvandlingsoperatorer public static. Exakt en av de berörda typerna måste vara den typ som deklarerar operatorn.

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 wrappertyp

Omvandlingar är särskilt användbara för tunna wrappertyper som stärker typsystemet utan att skapa friktion. Här omvandlas en NonEmptyString implicit till string, men det krävs en explicit cast för att skapa 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);
    }
}

Prova själv

Definiera en wrapper med en implicit omvandling utåt (säker) och en explicit omvandling inåt (validerad). Lägg märke till åt vilket håll en cast behövs.

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

Snabb kontroll

Välj rätt typ av omvandling.

Sammanfattning

Användardefinierade omvandlingar gör att dina typer kan samverka på ett smidigt sätt.

  • implicit operator för alltid säkra omvandlingar utan dataförlust.
  • explicit operator när data kan gå förlorad eller omvandlingen kan misslyckas.
  • Omvandlingar kan rikta sig mot inbyggda eller egna typer, i båda riktningarna.
  • De är public static och deklareras av en av de berörda typerna.
Gratis att börja

Lär dig C# med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
93
Lektioner
346

Vanliga frågor

Är lektionen ”Användardefinierade konverteringar” gratis?

Ja – hela texten till ”Användardefinierade konverteringar” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i C# Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i C# Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Användardefinierade konverteringar”?

Lägg till implicita och explicita konverteringsoperatorer. Ni övar på C# Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig C# Academy?

Du behöver inga förkunskaper. Utbildningen i C# Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.

Hur lång tid tar lektionen ”Användardefinierade konverteringar”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här C# Academy-lektionen?

Ja. Varje C# Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Överlagra aritmetiska operatorer
  2. Överlagra jämförelseoperatorer
  3. Användardefinierade konverteringar
  4. God praxis för operatoröverlagring
← Tillbaka till C# Academy