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