Ricerca…
Osservazioni
La trasmissione non è la stessa cosa di Conversione . È possibile convertire il valore di stringa "-1" in un valore intero ( -1 ), ma ciò deve essere eseguito tramite metodi di libreria come Convert.ToInt32() o Int32.Parse() . Non può essere fatto usando direttamente la sintassi del cast.
Trasmetti un oggetto a un tipo di base
Date le seguenti definizioni:
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";
}
}
Trasmettere un oggetto ad un esempio di tipo base:
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
Casting esplicito
Se si sa che un valore è di un tipo specifico, è possibile eseguirlo esplicitamente su quel tipo per poterlo utilizzare in un contesto in cui è necessario quel tipo.
object value = -1;
int number = (int) value;
Console.WriteLine(Math.Abs(number));
Se provassimo a passare il value direttamente a Math.Abs() , avremmo ottenuto un'eccezione in fase di compilazione perché Math.Abs() non ha un sovraccarico che accetta un object come parametro.
Se non è possibile eseguire il cast di un value su un int , la seconda riga in questo esempio genera una InvalidCastException
Safe Explicit Casting (operatore `as`)
Se non sei sicuro che un valore sia del tipo che pensi di essere, puoi lanciarlo in sicurezza usando l'operatore as . Se il valore non è di quel tipo, il valore risultante sarà null .
object value = "-1";
int? number = value as int?;
if(number != null)
{
Console.WriteLine(Math.Abs(number.Value));
}
Si noti che null valori null non hanno alcun tipo, quindi la parola chiave as renderà sicuramente null quando si esegue il cast di qualsiasi valore null .
Casting implicito
Un valore verrà automaticamente convertito nel tipo appropriato se il compilatore sa che può sempre essere convertito in quel tipo.
int number = -1;
object value = number;
Console.WriteLine(value);
In questo esempio, non è stato necessario utilizzare la tipica sintassi di trasmissione esplicita perché il compilatore sa che tutti gli int possono essere trasmessi agli object s. In effetti, potremmo evitare di creare variabili e passare -1 direttamente come argomento di Console.WriteLine() che si aspetta un object .
Console.WriteLine(-1);
Controllo della compatibilità senza casting
Se è necessario sapere se il tipo di un valore estende o implementa un determinato tipo, ma non si desidera eseguire effettivamente il cast come quel tipo, è possibile utilizzare l'operatore is .
if(value is int)
{
Console.WriteLine(value + "is an int");
}
Conversioni numeriche esplicite
Gli operatori di casting espliciti possono essere utilizzati per eseguire conversioni di tipi numerici, anche se non si estendono o si implementano a vicenda.
double value = -1.1;
int number = (int) value;
Si noti che nei casi in cui il tipo di destinazione ha meno precisione rispetto al tipo originale, la precisione andrà persa. Ad esempio, -1.1 come valore doppio nell'esempio precedente diventa -1 come valore intero.
Inoltre, le conversioni numeriche si basano sui tipi in fase di compilazione, quindi non funzioneranno se i tipi numerici sono stati "incapsulati" in oggetti.
object value = -1.1;
int number = (int) value; // throws InvalidCastException
Operatori di conversione
In C #, i tipi possono definire operatori di conversione personalizzati, che consentono di convertire i valori in e da altri tipi utilizzando cast espliciti o impliciti. Ad esempio, considera una classe che intende rappresentare un'espressione 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 + ")");
}
}
Se volessimo creare un JsExpression che rappresenti un confronto tra due valori JavaScript, potremmo fare qualcosa del genere:
JsExpression intExpression = new JsExpression("-1");
JsExpression doubleExpression = new JsExpression("-1.0");
Console.WriteLine(intExpression.IsEqualTo(doubleExpression)); // (-1 == -1.0)
Ma possiamo aggiungere alcuni operatori di conversione espliciti a JsExpression , per consentire una conversione semplice quando si utilizza il cast esplicito.
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)
Oppure, potremmo cambiare questi operatori in implicito per rendere la sintassi molto più semplice.
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)
Operazioni di fusione LINQ
Supponiamo di avere tipi come il seguente:
interface IThing { }
class Thing : IThing { }
LINQ consente di creare una proiezione che modifica il tipo generico in fase di compilazione di un oggetto IEnumerable<> tramite i metodi di estensione Enumerable.Cast<>() ed Enumerable.OfType<>() .
IEnumerable<IThing> things = new IThing[] {new Thing()};
IEnumerable<Thing> things2 = things.Cast<Thing>();
IEnumerable<Thing> things3 = things.OfType<Thing>();
Quando viene valutato things2 , il metodo Cast<>() proverà a things2 tutti i valori nelle things in Thing s. Se incontra un valore che non può essere lanciato, verrà lanciata una InvalidCastException .
Quando viene valutato things3 , il OfType<>() farà lo stesso, eccetto che se incontra un valore che non può essere lanciato, semplicemente ometterà quel valore anziché lanciare un'eccezione.
A causa del tipo generico di questi metodi, non possono richiamare operatori di conversione o eseguire conversioni numeriche.
double[] doubles = new[]{1,2,3}.Cast<double>().ToArray(); // Throws InvalidCastException
Puoi semplicemente eseguire un cast all'interno di .Select() come soluzione alternativa:
double[] doubles = new[]{1,2,3}.Select(i => (double)i).ToArray();