Szukaj…


Uwagi

Przesyłanie nie jest tym samym, co konwersja . Możliwe jest przekonwertowanie wartości ciągu "-1" na wartość całkowitą ( -1 ), ale należy to zrobić metodami bibliotecznymi, takimi jak Convert.ToInt32() lub Int32.Parse() . Nie można tego zrobić bezpośrednio przy użyciu składni rzutowania.

Rzuć obiekt na typ podstawowy

Biorąc pod uwagę następujące definicje:

public interface IMyInterface1
{
    string GetName();
}

public interface IMyInterface2
{
    string GetName();
}

public class MyClass : IMyInterface1, IMyInterface2
{
    string IMyInterface1.GetName()
    {
        return "IMyInterface1";
    }

    string IMyInterface2.GetName()
    {
        return "IMyInterface2";
    }
}

Rzutowanie obiektu na przykład typu podstawowego:

    MyClass obj = new MyClass();

    IMyInterface1 myClass1 = (IMyInterface1)obj;
    IMyInterface2 myClass2 = (IMyInterface2)obj;

    Console.WriteLine("I am : {0}", myClass1.GetName());
    Console.WriteLine("I am : {0}", myClass2.GetName());

    // Outputs :
    // I am : IMyInterface1
    // I am : IMyInterface2

Jawne przesyłanie

Jeśli wiesz, że wartość jest określonego typu, możesz jawnie rzucić ją na ten typ, aby użyć go w kontekście, w którym ten typ jest potrzebny.

object value = -1;
int number = (int) value;
Console.WriteLine(Math.Abs(number));

Gdybyśmy spróbowali przekazać value bezpośrednio do Math.Abs() , otrzymalibyśmy wyjątek czasu kompilacji, ponieważ Math.Abs() nie ma przeciążenia, które przyjmuje object jako parametr.

Jeśli value nie może być oddane do int , potem druga linia w tym przykładzie będzie rzucić InvalidCastException

Bezpieczne przesyłanie jawne (operator `as`)

Jeśli nie masz pewności, czy wartość jest tego typu, co myślisz, możesz bezpiecznie rzucić ją za pomocą operatora as . Jeśli wartość nie jest tego typu, wynikowa wartość będzie null .

object value = "-1";
int? number = value as int?;
if(number != null)
{
    Console.WriteLine(Math.Abs(number.Value));
}

Zauważ, że wartości null nie mają typu, więc słowo kluczowe as bezpiecznie zwróci null podczas rzutowania dowolnej wartości null .

Implicit Casting

Wartość zostanie automatycznie rzutowana na odpowiedni typ, jeśli kompilator wie, że zawsze można ją przekonwertować na ten typ.

int number = -1;
object value = number;
Console.WriteLine(value);

W tym przykładzie, nie trzeba korzystać z typową składnię rozstrzygający wyraźny, ponieważ kompilator wie wszystko int s mogą być oddane do object s. W rzeczywistości możemy uniknąć tworzenia zmiennych i przekazać -1 bezpośrednio jako argument Console.WriteLine() który oczekuje object .

Console.WriteLine(-1);

Sprawdzanie zgodności bez rzutowania

Jeśli chcesz wiedzieć, czy typ wartości rozszerza lub implementuje dany typ, ale nie chcesz go rzutować jako tego typu, możesz użyć operatora is .

if(value is int)
{
   Console.WriteLine(value + "is an int");
}

Jawne konwersje numeryczne

Operatorów rzutowania jawnego można używać do wykonywania konwersji typów numerycznych, nawet jeśli się nie rozszerzają ani nie implementują.

double value = -1.1;
int number = (int) value;

Pamiętaj, że w przypadkach, w których typ docelowy ma mniejszą dokładność niż typ oryginalny, precyzja zostanie utracona. Na przykład -1.1 jako wartość podwójna w powyższym przykładzie staje się -1 jako wartość całkowita.

Ponadto konwersje numeryczne opierają się na typach czasu kompilacji, więc nie będą działać, jeśli typy numeryczne zostały „umieszczone w ramkach” w obiektach.

object value = -1.1;
int number = (int) value; // throws InvalidCastException

Operatorzy konwersji

W języku C # typy mogą definiować niestandardowe operatory konwersji , które umożliwiają konwersję wartości na inne typy i z nich przy użyciu rzutowań jawnych lub niejawnych. Rozważmy na przykład klasę, która ma reprezentować wyrażenie JavaScript:

public class JsExpression
{
    private readonly string expression;
    public JsExpression(string rawExpression)
    {
        this.expression = rawExpression;
    }
    public override string ToString()
    {
        return this.expression;
    }
    public JsExpression IsEqualTo(JsExpression other)
    {
        return new JsExpression("(" + this + " == " + other + ")");
    }
}

Gdybyśmy chcieli stworzyć JsExpression reprezentujący porównanie dwóch wartości JavaScript, moglibyśmy zrobić coś takiego:

JsExpression intExpression = new JsExpression("-1");
JsExpression doubleExpression = new JsExpression("-1.0");
Console.WriteLine(intExpression.IsEqualTo(doubleExpression)); // (-1 == -1.0)

Możemy jednak dodać jawne operatory konwersji do JsExpression , aby umożliwić prostą konwersję przy użyciu jawnego rzutowania.

public static explicit operator JsExpression(int value)
{
    return new JsExpression(value.ToString());
}
public static explicit operator JsExpression(double value)
{
    return new JsExpression(value.ToString());
}

// Usage:
JsExpression intExpression = (JsExpression)(-1);
JsExpression doubleExpression = (JsExpression)(-1.0);
Console.WriteLine(intExpression.IsEqualTo(doubleExpression)); // (-1 == -1.0)

Lub możemy zmienić te operatory na domniemane, aby uprościć składnię.

public static implicit operator JsExpression(int value)
{
    return new JsExpression(value.ToString());
}
public static implicit operator JsExpression(double value)
{
    return new JsExpression(value.ToString());
}

// Usage:
JsExpression intExpression = -1;
Console.WriteLine(intExpression.IsEqualTo(-1.0)); // (-1 == -1.0)

Operacje rzutowania LINQ

Załóżmy, że masz typy takie jak następujące:

interface IThing {  }
class Thing : IThing {  }

LINQ umożliwia utworzenie projekcji, która zmienia ogólny typ IEnumerable<> za pomocą Enumerable.Cast<>() i Enumerable.OfType<>() .

IEnumerable<IThing> things = new IThing[] {new Thing()};
IEnumerable<Thing> things2 = things.Cast<Thing>();
IEnumerable<Thing> things3 = things.OfType<Thing>();

Gdy things2 jest oceniane, metoda Cast<>() spróbuje rzutować wszystkie wartości w things do Thing s. Jeśli napotka wartość, której nie można rzutować, zostanie InvalidCastException .

Gdy things3 jest oceniane, OfType<>() zrobi to samo, z tym wyjątkiem, że jeśli napotka wartość, której nie można rzutować, po prostu pominie tę wartość, zamiast zgłosić wyjątek.

Ze względu na ogólny typ tych metod nie mogą wywoływać Operatorów konwersji ani wykonywać konwersji numerycznych.

double[] doubles = new[]{1,2,3}.Cast<double>().ToArray(); // Throws InvalidCastException

Możesz po prostu wykonać rzutowanie w .Select() jako obejście:

double[] doubles = new[]{1,2,3}.Select(i => (double)i).ToArray();


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow