Errore del compilatore CS0029

Impossibile convertire implicitamente 'tipo' in 'tipo'.

Il compilatore richiede una conversione esplicita. Può ad esempio essere necessario eseguire il cast di un r-value in modo che sia dello stesso tipo di un l-value oppure fornire routine di conversione per il supporto di determinati overload di operatori.

Le conversioni devono essere eseguite durante l'assegnazione di una variabile di un tipo a una variabile di un altro tipo. Quando si effettua un'assegnazione tra variabili di tipo diverso, è necessario che il tipo a destra dell'operatore di assegnazione venga convertito dal compilatore nel tipo a sinistra dell'operatore di assegnazione. Nel seguente codice ad esempio:

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

i = lng; effettua un'assegnazione, tuttavia i tipi di dati delle variabili a sinistra e a destra dell'operatore di assegnazione non corrispondono. Prima di effettuare l'assegnazione, la variabile lng, che è tipo long, viene convertita in modo implicito dal compilatore in un tipo int. La conversione avviene in modo implicito poiché nel codice non è specificato in modo esplicito che dovrà essere eseguita dal compilatore. Il problema è dovuto al fatto che questa viene considerata una conversione verso un tipo di dati più piccolo e nel compilatore questo tipo di conversioni implicite non sono consentite in quanto possono causare perdite di dati.

Una conversione verso un tipo di dati più piccolo si verifica quando un tipo di dati occupa una maggiore quantità di spazio in memoria rispetto al tipo di dati in cui viene convertito. La conversione, ad esempio, di un tipo long in un tipo int è considerata una conversione verso un tipo di dati più piccolo. Un tipo long occupa 8 byte di memoria, mentre un tipo int occupa 4 byte. Per comprendere come può verificarsi una perdita di dati, considerare il codice di esempio riportato di seguito:

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

Nella variabile lng ora è contenuto un valore che non può essere memorizzato nella variabile i perché è troppo grande. Se si converte questo valore in un tipo int, una parte dei dati andrà persa e il valore convertito non sarà lo stesso valore disponibile prima della conversione.

Con una conversione verso un tipo di dati più grande si ottiene l'effetto opposto a una conversione verso un tipo di dati più piccolo. Una conversione verso un tipo di dati più grande si verifica quando un tipo di dati occupa una minore quantità di spazio in memoria rispetto al tipo di dati in cui viene convertito. Di seguito è riportato un esempio di conversione verso un tipo di dati più grande:

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

Si noti la differenza tra questo esempio di codice e il precedente. In questo caso la variabile lng si trova a sinistra dell'operatore di assegnazione, quindi diventa la destinazione di assegnazione. Prima di effettuare l'assegnazione, è necessario eseguire nel compilatore la conversione implicita della variabile i, che è di tipo int, nel tipo long. Tale conversione è verso un tipo di dati più grande in quanto si converte da un tipo che occupa 4 byte di memoria (il tipo int) in un tipo che occupa 8 byte di memoria (il tipo long). Le conversioni implicite verso un tipo di dati più grande sono consentite, in quanto non possono verificarsi perdite di dati. Qualsiasi valore memorizzato in un tipo int può essere contenuto in un tipo long.

Poiché le conversioni implicite verso un tipo di dati più piccolo non sono consentite, per compilare il codice è necessario convertire il tipo di dati in modo esplicito. Le conversioni esplicite vengono effettuate tramite cast. Cast è il termine utilizzato in C# per descrivere la conversione di un tipo di dati in un altro tipo di dati. Per consentire la compilazione del codice è necessario utilizzare la seguente sintassi:

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

Nella terza riga di codice viene specificato che prima di procedere all'assegnazione il compilatore dovrà convertire in modo esplicito la variabile lng, che è di tipo long, in un tipo int. Una conversione verso un tipo di dati più piccolo, come già precisato, può causare possibili perdite di dati. Si consiglia di utilizzare con attenzione le conversioni verso tipi di dati più piccoli. Anche se il codice viene compilato, è possibile che in fase di esecuzione vengano generati risultati imprevisti.

Queste indicazioni sono applicabili solo per i tipi di valore. Quando si utilizzano tipi di valore, si utilizzano direttamente i dati memorizzati nella variabile. In .NET Framework sono tuttavia disponibili anche tipi di riferimento. Quando si utilizzano tipi di riferimento, si utilizza in effetti un riferimento a una variabile e non i dati effettivi. Esempi di tipi di riferimento sono classi, interfacce e matrici. Per convertire in modo implicito o esplicito un tipo di riferimento in un altro è necessario che il compilatore consenta questa specifica conversione o che gli operatori di conversione appropriati vengano implementati.

Il seguente codice di esempio genera l'errore 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()
   {
      MyInt myInt = new MyInt();
      int i = myInt; // CS0029
   }
}

Vedere anche

Riferimenti

Operatori di conversione (Guida per programmatori C#)