Recherche…


Remarques

Le casting est différent de la conversion . Il est possible de convertir la valeur de chaîne "-1" en une valeur entière ( -1 ), mais cela doit être fait par des méthodes de bibliothèque telles que Convert.ToInt32() ou Int32.Parse() . Cela ne peut pas être fait en utilisant directement la syntaxe de casting.

Lancer un objet sur un type de base

Compte tenu des définitions suivantes:

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";
    }
}

Lancer un objet dans un exemple de type de 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 explicite

Si vous savez qu'une valeur est d'un type spécifique, vous pouvez la convertir explicitement dans ce type afin de l'utiliser dans un contexte où ce type est nécessaire.

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

Si nous essayions de transmettre directement la value à Math.Abs() , nous obtiendrions une exception à la Math.Abs() car Math.Abs() n'a pas de surcharge qui prend un object comme paramètre.

Si la value n'a pas pu être InvalidCastException en int , la deuxième ligne de cet exemple InvalidCastException une InvalidCastException

Casting explicite sûr (opérateur `as`)

Si vous ne savez pas si une valeur est du type que vous pensez, vous pouvez la lancer en toute sécurité en utilisant l'opérateur as . Si la valeur n'est pas de ce type, la valeur résultante sera null .

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

Notez que null valeurs null n'ont pas de type, de sorte as mot-clé as produira en toute sécurité null lors de la conversion de toute valeur null .

Casting implicite

Une valeur sera automatiquement convertie dans le type approprié si le compilateur sait qu'il peut toujours être converti en ce type.

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

Dans cet exemple, nous n'avons pas eu besoin d'utiliser la syntaxe de transtypage explicite car le compilateur sait que tous les int s peuvent être convertis en object s. En fait, nous pourrions éviter de créer des variables et transmettre directement -1 comme argument de Console.WriteLine() qui attend un object .

Console.WriteLine(-1);

Vérification de la compatibilité sans coulée

Si vous avez besoin de savoir si le type d'une valeur étend ou implémente un type donné, mais que vous ne voulez pas le lancer comme tel, vous pouvez utiliser l'opérateur is .

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

Conversions numériques explicites

Les opérateurs de transtypage explicite peuvent être utilisés pour effectuer des conversions de types numériques, même s'ils ne s’étendent pas ou s’implémentent mutuellement.

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

Notez que dans les cas où le type de destination est moins précis que le type d'origine, la précision sera perdue. Par exemple, -1.1 tant que valeur double dans l'exemple ci-dessus devient -1 tant que valeur entière.

De même, les conversions numériques reposent sur des types à la compilation, de sorte qu'elles ne fonctionneront pas si les types numériques ont été "encadrés" dans des objets.

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

Opérateurs de conversion

En C #, les types peuvent définir des opérateurs de conversion personnalisés, qui permettent de convertir les valeurs depuis et vers d'autres types en utilisant des conversions explicites ou implicites. Par exemple, considérez une classe destinée à représenter une expression 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 + ")");
    }
}

Si nous voulions créer une expression JsExpression représentant une comparaison de deux valeurs JavaScript, nous pourrions faire quelque chose comme ceci:

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

Mais nous pouvons ajouter des opérateurs de conversion explicites à JsExpression , pour permettre une conversion simple lors de l'utilisation de transtypage explicite.

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)

Ou, nous pourrions changer ces opérateurs en implicite pour rendre la syntaxe beaucoup plus simple.

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)

Opérations de coulée LINQ

Supposons que vous ayez des types comme ceux-ci:

interface IThing {  }
class Thing : IThing {  }

LINQ vous permet de créer une projection qui modifie le type générique de compilation d'un IEnumerable<> via les méthodes d'extension Enumerable.Cast<>() et Enumerable.OfType<>() .

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

Lorsque things2 est évalué, la méthode Cast<>() essaiera de transposer toutes les valeurs des things dans Thing s. S'il rencontre une valeur qui ne peut pas être InvalidCastException , une InvalidCastException sera lancée.

Lorsque things3 est évalué, la OfType<>() fera de même, sauf que si elle rencontre une valeur qui ne peut pas être convertie, elle omettra simplement cette valeur plutôt que de lancer une exception.

En raison du type générique de ces méthodes, ils ne peuvent pas appeler des opérateurs de conversion ou effectuer des conversions numériques.

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

Vous pouvez simplement effectuer un transtypage dans un .Select() comme solution de contournement:

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


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow