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


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow