C# Academy · Oppitunti

Käyttäjän määrittämät muunnokset

Lisätkää implisiittiset ja eksplisiittiset muunnosoperaattorit.

Oppitunti 3/413 vaihetta

Käyttäjän määrittämät muunnokset on ilmainen C# Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C# Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C# Academy-kurssilla on yhteensä 4 oppituntia.

Käyttäjän määrittämät muunnokset

C#:ssa tyyppi voi määritellä, miten se muunnetaan toiseksi tyypiksi tai miten toinen tyyppi muunnetaan siksi käyttämällä implicit- ja explicit-operaattoreita. Implisiittiset muunnokset tapahtuvat automaattisesti, kun taas eksplisiittiset muunnokset edellyttävät tyyppimuunnosta.

Implisiittinen muunnos

Käyttäkää implicit operator-operaattoria, kun muunnos on aina turvallinen eikä hävitä tietoa. Kääntäjä soveltaa sitä automaattisesti kaikkialla, missä kohdetyyppiä odotetaan.

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

Eksplisiittinen muunnos

Käyttäkää explicit operator-operaattoria, kun muunnos voi hävittää tietoa tai epäonnistua. Kutsujan on kirjoitettava tyyppimuunnos, mikä ilmaisee riskin hyväksymisen.

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

Muuntaminen omaksi tyypiksi

Muunnos voi tapahtua myös toiseen suuntaan: toisesta tyypistä omaksi tyypiksenne. Tässä implicit-operaattori muodostaa Celsius-arvon raakaluvusta 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);
    }
}

Implisiittinen vai eksplisiittinen: valinta

Nyrkkisääntö on seuraava: käytä implisiittistä muunnosta vain, jos tietoa ei koskaan häviä eikä muunnos koskaan aiheuta poikkeusta. Jos tarkkuutta voi hävitä, arvo voi ylivuotaa tai muunnos voi epäonnistua, tee siitä eksplisiittinen.

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

Muunnokset omien tyyppien välillä

Muunnokset eivät rajoitu sisäänrakennettuihin tyyppeihin. Voit muuntaa kaksi omaa tyyppiä keskenään, esimerkiksi napakoordinaatit suorakulmaisiksi koordinaateiksi.

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

Muunnokset toimivat yhdessä operaattorien kanssa

Kun muunnos on määritelty, arvo osallistuu kohdetyypin lausekkeisiin. Implisiittisen double-muunnoksen ansiosta tyyppiä voi käyttää suoraan aritmeettisissa laskuissa.

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

Vältä yllättäviä implisiittisiä muunnoksia

Implisiittiset muunnokset, jotka eivät ole ilmeisen turvallisia, voivat peittää virheitä, koska kääntäjä tekee ne kaikessa hiljaisuudessa. Jos olet epävarma, suosi eksplisiittistä muunnosta, jotta tarkoitus näkyy koodissa.

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

Muunnosoperaattorit ovat static

Muiden operaattorien tavoin muunnosoperaattorit ovat public static. Tasaan yhden mukana olevista tyypeistä on oltava operaattorin määrittelevä tyyppi.

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

Käytännöllinen wrapper-tyyppi

Muunnoksista on eniten hyötyä ohuille wrapper-tyypeille, jotka vahvistavat tyyppijärjestelmää ilman ylimääräistä vaivaa. Tässä NonEmptyString muunnetaan implisiittisesti tyypiksi string, mutta sen luominen edellyttää eksplisiittistä castia.

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

Kokeile itse

Määrittele wrapper, jolla on implisiittinen turvallinen muunnos ulospäin ja eksplisiittinen validoitu muunnos sisäänpäin. Huomaa, kumpi suunta edellyttää castia.

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

Pikatarkistus

Valitse oikea muunnostyyppi.

Kertaus

Käyttäjän määrittämät muunnokset mahdollistavat tyyppien sujuvan yhteistoiminnan.

  • implicit operator aina turvallisiin ja häviöttömiin muunnoksiin.
  • explicit operator, kun tietoa voi hävitä tai muunnos voi epäonnistua.
  • Muunnokset voivat kohdistua sisäänrakennettuihin tai omiin tyyppeihin kumpaankin suuntaan.
  • Ne ovat public static ja yhden mukana olevan tyypin määrittelemiä.
Aloita maksutta

Opi C# tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
93
Oppitunnit
346

Usein kysytyt kysymykset

Onko oppitunti ”Käyttäjän määrittämät muunnokset” ilmainen?

Kyllä – oppitunnin ”Käyttäjän määrittämät muunnokset” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C# Academy-kurssin, päivitä CoddyKit PROhon. C# Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Käyttäjän määrittämät muunnokset”?

Lisätkää implisiittiset ja eksplisiittiset muunnosoperaattorit. Harjoittelet C# Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni C# Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin C# Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”Käyttäjän määrittämät muunnokset”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä C# Academy-oppitunnilla?

Kyllä. Jokainen C# Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Aritmeettisten operaattorien ylikuormitus
  2. Vertailuoperaattorien ylikuormitus
  3. Käyttäjän määrittämät muunnokset
  4. Operaattorien ylikuormituksen parhaat käytännöt
← Takaisin: C# Academy