Share via


Erreur du compilateur CS0029

Impossible de convertir implicitement le type 'type' en 'type'

Le compilateur requiert une conversion explicite. Par exemple, il se peut que vous deviez effectuer un cast sur une valeur r en type identique à celui d’une valeur l. Vous pouvez aussi avoir à fournir des routines de conversion pour prendre en charge certaines surcharges d’opérateur.

Les conversions doivent se produire lors de l’assignation d’une variable d’un type à une variable d’un autre type. Lors de l’assignation entre des variables de types différents, le compilateur doit convertir le type situé à droite de l’opérateur d’assignation dans le type situé à gauche de ce même opérateur. Prenez le code ci-dessous :

int i = 50;
long lng = 100;
i = lng;

i = lng; effectue une assignation, mais les types de données des variables situées de part et d’autre de l’opérateur d’assignation ne correspondent pas. Avant de procéder à l’assignation, le compilateur convertit implicitement la variable lng, qui est de type long, en type int. Cela est implicite, car aucun code n’a indiqué explicitement au compilateur d’effectuer cette conversion. Il s’agit néanmoins d’une conversion restrictive et c’est là où se pose un problème ; en effet, le compilateur n’autorise pas les conversions restrictives implicites, car il existe un risque potentiel de perte de données.

Une conversion restrictive existe lors de la conversion en un type de données qui occupe moins d’espace de stockage en mémoire que le type de données à partir duquel vous effectuez la conversion. Par exemple, la conversion d’un type long en type int est considérée comme une conversion restrictive. Le type long occupe 8 octets de mémoire tandis que le type int en occupe 4. Pour voir dans quelles conditions survient la perte de données, prenez l’exemple suivant :

int i = 50;
long lng = 3147483647;
i = lng;

La variable lng contient maintenant une valeur qui ne peut être stockée dans la variable i du fait de sa trop grande taille. Si vous deviez convertir cette valeur en type int, vous perdriez certaines données et la valeur convertie ne serait pas la même que la valeur avant la conversion.

Une conversion étendue est le contraire d’une conversion restrictive. Dans ce cas, vous effectuez une conversion en un type de données qui occupe plus d’espace de stockage en mémoire que le type de données à partir duquel vous effectuez la conversion. En voici un exemple :

int i = 50;
long lng = 100;
lng = i;

Notez la différence entre cet exemple de code et le premier. Cette fois, la variable lng se trouve à gauche de l’opérateur d’assignation, de sorte qu’elle est la cible de votre assignation. Pour que l’assignation puisse être effectuée, le compilateur doit implicitement convertir la variable i, qui est de type int, en type long. Il s’agit d’une conversion étendue puisqu’elle s’effectue à partir d’un type qui occupe 4 octets de mémoire (int) vers un type qui en occupe 8 (long). Les conversions étendues implicites sont autorisées, car il n’existe aucun risque potentiel de perte de données. Toute valeur pouvant être stockée en type int peut l’être aussi en long.

Les conversions restrictives implicites n’étant pas autorisées, il faut donc, pour compiler ce code, convertir explicitement le type de données. Les conversions explicites sont effectuées à l’aide du cast. Le cast est le terme utilisé en C# pour décrire la conversion d’un type de données en un autre. Pour obtenir le code à compiler, vous devez utiliser la syntaxe suivante :

int i = 50;
long lng = 100;
i = (int) lng;   // Cast to int.

La troisième ligne de code indique au compilateur de convertir explicitement la variable lng, qui est de type long, en type int avant de procéder à l’assignation. N’oubliez pas qu’avec une conversion restrictive, il existe un risque de perte de données. Les conversions restrictives doivent être utilisées avec précaution car, même si la compilation est effectuée, des résultats inattendus peuvent se produire au moment de l’exécution.

Cette présentation ne concerne que les types valeur. En utilisant les types valeur, vous travaillez directement avec les données stockées dans la variable. Toutefois, .NET possède également des types référence. En utilisant les types référence, vous travaillez avec une référence à une variable et non avec les données réelles. Les classes, les interfaces et les tableaux sont des exemples de types référence. Vous ne pouvez implicitement ou explicitement effectuer une conversion d’un type référence en un autre que si le compilateur autorise la conversion spécifique ou si les opérateurs de conversion appropriés sont implémentés.

L’exemple suivant génère l’erreur CS0029 :

// CS0029.cs
public class MyInt
{
    private int x = 0;

    // Uncomment this conversion routine to resolve CS0029.
    /*
    public static implicit operator int(MyInt i)
    {
        return i.x;
    }
    */

    public static void Main()
    {
        var myInt = new MyInt();
        int i = myInt; // CS0029
    }
}

Voir aussi