Dela via


Konvertering av gjutning och typ (programmeringsguide för C#)

Eftersom C# är statiskt skrivet vid kompileringstillfället kan den inte deklareras igen eller tilldelas ett värde av en annan typ när en variabel har deklarerats, såvida inte den typen implicit kan konverteras till variabelns typ. Det string går till exempel inte att implicit konvertera till int. När du har deklarerat i som en intkan du därför inte tilldela strängen "Hello" till den, som följande kod visar:

int i;

// error CS0029: can't implicitly convert type 'string' to 'int'
i = "Hello";

Du kan dock ibland behöva kopiera ett värde till en variabel eller metodparameter av en annan typ. Du kan till exempel ha en heltalsvariabel som du behöver skicka till en metod vars parameter skrivs som double. Eller så kan du behöva tilldela en klassvariabel till en variabel av en gränssnittstyp. Den här typen av åtgärder kallas typkonverteringar. I C# kan du utföra följande typer av konverteringar:

  • Implicita konverteringar: Ingen särskild syntax krävs eftersom konverteringen alltid lyckas och inga data går förlorade. Exempel är konverteringar från mindre till större integraltyper och konverteringar från härledda klasser till basklasser.

  • Explicita konverteringar (casts): Explicita konverteringar kräver ett cast-uttryck. Casting krävs när information kan gå förlorad i konverteringen, eller när konverteringen kanske inte lyckas av andra skäl. Vanliga exempel är numerisk konvertering till en typ som har mindre precision eller ett mindre intervall och konvertering av en basklassinstans till en härledd klass.

  • Användardefinierade konverteringar: Användardefinierade konverteringar använder särskilda metoder som du kan definiera för att aktivera explicita och implicita konverteringar mellan anpassade typer som inte har en basklass-härledd klassrelation. Mer information finns i Användardefinierade konverteringsoperatorer.

  • Konverteringar med hjälpklasser: Om du vill konvertera mellan icke-kompatibla typer, till exempel heltal och System.DateTime objekt, eller hexadecimala strängar och bytematriser, kan du använda System.BitConverter klassen, System.Convert klassen och Parse metoderna för de inbyggda numeriska typerna, till exempel Int32.Parse. Mer information finns i Konvertera en bytematris till en int, Så här konverterar du en sträng till ett tal och Konvertera mellan hexadecimala strängar och numeriska typer.

Implicita konverteringar

För inbyggda numeriska typer kan en implicit konvertering göras när värdet som ska lagras får plats i variabeln utan att trunkeras eller avrundas. För integraltyper innebär det att källtypens intervall är en lämplig delmängd av intervallet för måltypen. En variabel av typen long (64-bitars heltal) kan till exempel lagra valfritt värde som ett int (32-bitars heltal) kan lagra. I följande exempel konverterar kompilatorn implicit värdet num för till höger till en typ long innan den tilldelas till bigNum.

// Implicit conversion. A long can
// hold any value an int can hold, and more!
int num = 2147483647;
long bigNum = num;

En fullständig lista över alla implicita numeriska konverteringar finns i avsnittet Implicita numeriska konverteringar i artikeln Inbyggda numeriska konverteringar.

För referenstyper finns alltid en implicit konvertering från en klass till någon av dess direkta eller indirekta basklasser eller gränssnitt. Ingen särskild syntax krävs eftersom en härledd klass alltid innehåller alla medlemmar i en basklass.

Derived d = new Derived();

// Always OK.
Base b = d;

Explicita konverteringar

Men om en konvertering inte kan göras utan risk för att förlora information, kräver kompilatorn att du utför en explicit konvertering, som kallas cast. En cast är ett sätt att uttryckligen informera kompilatorn om att du tänker göra konverteringen och att du är medveten om att dataförlust kan inträffa, eller att casten kan misslyckas vid körning. Om du vill utföra en gjutning anger du den typ som du konverterar till inom parenteser framför värdet eller variabeln som ska konverteras. Följande program kastar en dubbel till en int. Programmet kompilerar inte utan casten.

class Test
{
    static void Main()
    {
        double x = 1234.7;
        int a;
        // Cast double to int.
        a = (int)x;
        System.Console.WriteLine(a);
    }
}
// Output: 1234

En fullständig lista över explicita numeriska konverteringar som stöds finns i avsnittet Explicita numeriska konverteringar i artikeln Inbyggda numeriska konverteringar.

För referenstyper krävs en explicit gjutning om du behöver konvertera från en bastyp till en härledd typ:

// Create a new derived type.
Giraffe g = new Giraffe();

// Implicit conversion to base type is safe.
Animal a = g;

// Explicit conversion is required to cast back
// to derived type. Note: This will compile but will
// throw an exception at run time if the right-side
// object is not in fact a Giraffe.
Giraffe g2 = (Giraffe)a;

En gjuten åtgärd mellan referenstyper ändrar inte körningstypen för det underliggande objektet. Den ändrar bara typen av värde som används som referens till det objektet. Mer information finns i Polymorfism.

Typkonverteringsfel vid körning

I vissa referenstypkonverteringar kan kompilatorn inte avgöra om en cast är giltig. Det är möjligt att en gjuten åtgärd som kompileras korrekt misslyckas vid körning. Som du ser i följande exempel leder en typgjutning som misslyckas vid körningen till att en InvalidCastException genereras.

class Animal
{
    public void Eat() => System.Console.WriteLine("Eating.");

    public override string ToString() => "I am an animal.";
}

class Reptile : Animal { }
class Mammal : Animal { }

class UnSafeCast
{
    static void Main()
    {
        Test(new Mammal());

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }

    static void Test(Animal a)
    {
        // System.InvalidCastException at run time
        // Unable to cast object of type 'Mammal' to type 'Reptile'
        Reptile r = (Reptile)a;
    }
}

Metoden Test har en Animal parameter, vilket uttryckligen gjuter argumentet a till ett Reptile gör ett farligt antagande. Det är säkrare att inte göra antaganden, utan i stället kontrollera typen. C# tillhandahåller is-operatorn så att du kan testa kompatibiliteten innan du utför en cast. Mer information finns i How to safely cast using pattern matching and the as and is operators (Så här gjuter du säkert med mönstermatchning och som och är operatorer).

Språkspecifikation för C#

Mer information finns i avsnittet Konverteringar i C#-språkspecifikationen.

Se även