Come configurare smartphone e PC. Portale informativo
  • casa
  • Errori
  • Casting di tipi impliciti in C#. Conversione automatica del tipo

Casting di tipi impliciti in C#. Conversione automatica del tipo

La conversione implicita del tipo di dati viene eseguita dal compilatore C++, mentre la conversione esplicita dei dati viene eseguita dal programmatore stesso. Riguardo alla conversione del tipo di dati dirò quanto segue: "Il risultato di qualsiasi calcolo verrà convertito nel tipo di dati più accurato tra quelli coinvolti nel calcolo." Per chiaro esempio Presenterò una tabella con le conversioni del tipo di dati. Nella tabella considereremo l'operazione di divisione. Prendiamo come tipo di dati intero int, BENE tipo reale avremo i dati galleggiante.

Tabella 1: conversione esplicita e implicita del tipo di dati in C++
X Risultato della divisione Esempio
dividendo divisore privato x = 15 y = 2
int int int 15/2=7
int galleggiante galleggiante 15/2=7.5
galleggiante int galleggiante 15/2=7.5

Dalla tabella si vede che cambiando le variabili in posti diversi, il risultato rimane lo stesso (nel nostro caso si tratta del dividendo e del divisore). Tutto sulla conversione implicita del tipo di dati. Per quanto riguarda la conversione esplicita, è necessaria per eseguire alcune manipolazioni, modificando così il risultato del calcolo. Il modo più semplice per convertire esplicitamente i tipi di dati, ad esempio: diciamo che dobbiamo dividere i numeri 15 e 2, dividi! 15/2=7. Il risultato è lo stesso della tabella. Ma se fai piccole trasformazioni, ad esempio: 15.0/2=7.5 con questa divisione il numero 15 è reale, il che significa che il risultato sarà reale. Il numero 15 stesso non è cambiato da un punto di vista matematico, perché 15 = 15,0. La stessa tecnica potrebbe essere applicata a due, il risultato sarebbe lo stesso, oppure potrebbe essere applicata a due numeri contemporaneamente, ma perché, se uno dei due basta.

Un altro modo per convertire esplicitamente i tipi di dati è:

Float(15) / 2 // il risultato è 7,5, il numero 15 viene convertito nel tipo di dati float. double(15) / 2 // il risultato è 7,5 – la stessa cosa!!!

C++ fornisce anche operazione unaria tipo calchi:

Cast_statico(/*variabile o numero*/)

esempio: static_cast (15)/2 il risultato è 7,5
Esempio con una variabile:

Intret=15; static_cast (ret)/2 //il risultato è 7,5

Nel caso di una variabile, è necessario comprendere che nella riga 2 la variabile ret non viene convertita nel tipo di dati float, ma viene creata solo una copia temporanea della variabile ret con il tipo di dati float. Consideriamo in pratica tutti i metodi di esplicito e conversione implicita tipi di dati.

// pryeobrazovanie.cpp: definisce il punto di ingresso per l'applicazione console. #include "stdafx.h" #include #includere utilizzando lo spazio dei nomi std; int _tmain(int argc, _TCHAR* argv) ( int int_value15 = 15, int_value2 = 2; // dichiara due variabili di tipo int float valore_float15 = 15, valore_float2 = 2; // dichiara due variabili tipo galleggiante cout<< fixed << setprecision(2) // определяем, при выводе чисел с плавающей точкой, два знака после запятой << "15 / 2 = " << int_value15 / int_value2 << endl //неявное преобразование типов данных << "15 / 2 = " << int_value15 / float_value2 << endl //неявное преобразование типов данных << "15 / 2 = " << float_value15 / int_value2 << endl //неявное преобразование типов данных << "15 / 2 = " << float_value15 / float_value2 << endl; //неявное преобразование типов данных cout << "15.0 / 2 = " << 15.0 / 2 << endl // явное преобразование типа данных, число 15.0 - число с плавающей точкой << "15 / 2.0 = " << 15 / 2.0 << endl; // явное преобразование типа данных, число 2.0 - число с плавающей точкой cout << "float(int_value15) / int_value2 = " << float(int_value15) / int_value2 << endl // явное преобразование типа данных << "15 / double(2) = " << 15 / double(2) << endl; // используя приводимый тип как функцию cout << "static_cast(15) / 2 = " << static_cast(15) / 2 << endl // унарная операция приведения типа << "static_cast(15) = " << static_cast(15) << endl // можно печатать различные символы из таблицы ASCII, << "static_cast(20) = " << static_cast(20) << endl; // в скобочках прописываем код символа, который находим в таблице ASCII system("pause"); return 0; }

IN riga 5 collegato , questa libreria è necessaria per utilizzare vari manipolatori, nel nostro caso - fisso setprecision() . IN riga 10creato appositamente due variabili di tipo int , allo stesso modo hanno creato due variabili di tipo galleggiare dentro riga 11, queste variabili saranno necessarie per convertire i loro valori in altri tipi di dati. INriga 12dopo l'operatore cout e spostare le operazioni nel flusso di output << ci sono due manipolatori fisso e setprecision() . Manipolatore risolto - questo non è un manipolatore parametrizzato, poiché non accetta alcun parametro ed è scritto senza parentesi. Questo manipolatore viene utilizzato insieme a un manipolatore parametrizzato setprecision() ed esegue una visualizzazione fissa delle cifre decimali. Un manipolatore setprecision() visualizza il numero di cifre decimali e quello indicato tra parentesi. INlinee 13, 14, 15, 16vengono mostrati esempi di conversione implicita del tipo di dati da cui sono tratti questi esempiTabella 1. IN linee 17, 18mostra un modo per trasformare esplicitamente i dati. L'essenza di questo metodo è che è necessario aggiungere una virgola e uno zero al numero intero. INlinee 19, 20la conversione esplicita viene eseguita utilizzando tipi castabili come funzioni, all'interno delle parentesi delle quali è necessario specificare il valore o la variabile che deve essere convertita. Le righe 21, 22, 23 eseguono una conversione esplicita del tipo di dati utilizzando un'operazione di conversione dei dati unaria. Le parentesi indicano la variabile o il valore che deve essere convertito e i caratteri incorniciati < > il tipo di dati in cui convertire. Di seguito è mostrato un esempio di come funziona il programma (vedere Figura 1).

Figura 1: conversione esplicita e implicita dei tipi di dati C++

IN linee 22, 23 viene eseguita un'operazione di conversione dei dati unari e i numeri 15 e 20 vengono convertiti in char . Questo tipo di dati non ti è ancora noto, ma ricorda che char è un tipo di dati per l'archiviazione di file . Quindi, da Figura 1 puoi vedere che i simboli sono apparsi alla fine. Questi caratteri sono stati ottenuti convertendo i numeri in char . I numeri erano codici da . Pertanto, se è necessario emettere qualsiasi carattere dalla tabella ASCII, è possibile farlo come mostrato in linee 22, 23, sostituendo solo il codice richiesto.

Ultimo aggiornamento: 30/07/2018

Nel capitolo precedente abbiamo parlato di conversioni di oggetti di tipi semplici. Ora tocchiamo l'argomento della conversione degli oggetti di classe. Diciamo che abbiamo la seguente gerarchia di classi:

Classe Persona ( public string Nome ( get; set; ) public Persona(string nome) ( Nome = nome; ) public void Display() ( Console.WriteLine($"Persona (Nome)"); ) ) classe Impiegato: Persona ( public string Azienda ( get; set; ) public Dipendente(string nome, string azienda) : base(nome) ( Azienda = azienda; ) ) class Cliente: Persona ( public string Banca ( get; set; ) public Cliente(string nome, banca di stringhe): base(nome) ( Banca = banca; ) )

In questa gerarchia di classi, possiamo tracciare la seguente catena di ereditarietà: Oggetto (tutte le classi ereditano implicitamente dal tipo Oggetto) -> Persona -> Impiegato|Cliente.

Inoltre, in questa gerarchia di classi, i tipi base sono in alto e i tipi derivati ​​in basso.

Trasformazioni dal basso. Upcasting

Anche gli oggetti di un tipo derivato (che si trova nella parte inferiore della gerarchia) rappresentano il tipo di base. Ad esempio, un oggetto Employee è anche un oggetto della classe Person. Il che è naturale in linea di principio, poiché ogni dipendente (Employee) è una persona (Person). E possiamo scrivere, ad esempio, così:

Static void Main(string args) ( Employee dipendente = new Employee("Tom", "Microsoft"); Persona persona = dipendente; // conversione da Dipendente a Persona Console.WriteLine(person.Name); Console.ReadKey(); )

In questo caso, alla variabile persona, che rappresenta il tipo Persona, viene assegnato un riferimento all'oggetto Employee. Ma per memorizzare un riferimento a un oggetto di una classe in una variabile di un'altra classe, è necessario eseguire una conversione di tipo, in questo caso dal tipo Employee al tipo Person. E poiché Employee eredita dalla classe Person, viene eseguita automaticamente una conversione implicita verso l'alto, una conversione in un tipo che si trova al vertice della gerarchia di classi, ovvero nella classe base.

Di conseguenza, le variabili dipendente e persona punteranno allo stesso oggetto in memoria, ma la variabile persona avrà accesso solo alla parte che rappresenta la funzionalità del tipo Persona.

Altre trasformazioni ascendenti vengono eseguite in modo simile:

Persona persona2 = nuovo Cliente("Bob", "ContosoBank"); // conversione da cliente a persona

Qui, la variabile person2, che rappresenta il tipo Person, memorizza un riferimento all'oggetto Client, quindi c'è anche una conversione implicita verso l'alto dalla classe derivata Client al tipo Person di base.

Una conversione implicita verso l'alto si verificherà anche nel seguente caso:

Oggetto persona1 = nuovo Dipendente("Tom", "Microsoft"); // da Employee all'oggetto object person2 = new Client("Bob", "ContosoBank"); // dal Cliente all'oggetto oggetto persona3 = nuova Persona("Sam"); // dalla persona all'oggetto

Poiché il tipo di oggetto è il tipo base per tutti gli altri tipi, la conversione verrà eseguita automaticamente.

Trasformazioni verso il basso. Abbattimento

Ma oltre alle conversioni verso l'alto dal tipo derivato al tipo base, ci sono conversioni verso il basso o downcasting, dal tipo base al derivato. Ad esempio, nel codice seguente, la variabile person memorizza un riferimento all'oggetto Employee:

Dipendente dipendente = new Dipendente("Tom", "Microsoft"); Persona persona = dipendente; // conversione da dipendente a persona

E potrebbe sorgere la domanda se sia possibile accedere alla funzionalità del tipo Employee attraverso una variabile del tipo Person. Ma tali trasformazioni non avvengono automaticamente, perché non tutte le persone (oggetto Persona) sono dipendenti dell'impresa (oggetto Dipendente). E per la conversione al ribasso, devi applicare una conversione esplicita, indicando tra parentesi il tipo in cui vuoi convertire:

Dipendente dipendente = new Dipendente("Tom", "Microsoft"); Persona persona = dipendente; // conversione da Dipendente a Persona //Dipendente dipendente2 = persona; // questo non è possibile, è necessaria una conversione esplicita Dipendente impiegato2 = (Dipendente)persona; // conversione da persona a dipendente

Vediamo alcuni esempi di trasformazioni:

// Anche l'oggetto Employee è di tipo object object obj = new Employee("Bill", "Microsoft"); // per accedere alle funzionalità del tipo Employee, eseguire il cast dell'oggetto sul tipo Employee Employee emp = (Employee) obj; // l'oggetto Client rappresenta anche il tipo Person Person person = new Client("Sam", "ContosoBank"); // conversione da Persona a Cliente Client client = (Cliente)persona;

Nel primo caso, alla variabile obj viene assegnato un riferimento all'oggetto Employee, quindi possiamo convertire l'oggetto obj in qualsiasi tipo che si trova nella gerarchia di classi tra il tipo di oggetto e il tipo Employee.

Se dobbiamo accedere ad alcune proprietà o metodi individuali di un oggetto, non dobbiamo assegnare l'oggetto convertito a una variabile:

// Anche l'oggetto Employee è di tipo object object obj = new Employee("Bill", "Microsoft"); // conversione nel tipo Persona per chiamare il metodo Display ((Person)obj).Display(); // in questo modo // ((Employee)obj).Display(); // convertire in Employee per ottenere la stringa della proprietà Company comp = ((Employee)obj).Company;

Allo stesso tempo, è necessario prestare attenzione quando si effettuano tali trasformazioni. Ad esempio, cosa accadrà nel seguente caso:

// Anche l'oggetto Employee è di tipo object object obj = new Employee("Bill", "Microsoft"); // conversione nel tipo Client per ottenere la proprietà Bank string bank = ((Client)obj).Bank;

In questo caso, otterremo un errore perché la variabile obj memorizza un riferimento all'oggetto Employee. Questo oggetto è anche un oggetto di tipo oggetto e Persona, quindi possiamo convertirlo in quei tipi. Ma non possiamo convertirci al tipo Client.

Un altro esempio:

Dipendente emp = new Person("Tom"); // ! Errore Persona persona = nuova Persona("Bob"); Dipendente emp2 = (Dipendente) persona; // ! Errore

In questo caso, stiamo tentando di convertire un oggetto di tipo Person nel tipo Employee e l'oggetto Person non è un oggetto Employee.

Esistono diversi modi per evitare questi errori di conversione.

Metodi di trasformazione

Innanzitutto, puoi utilizzare la parola chiave as. Utilizzandolo, il programma tenta di convertire un'espressione in un tipo specifico senza generare un'eccezione. Se la conversione fallisce, l'espressione conterrà il valore null:

Persona persona = nuova Persona("Tom"); Employee emp = persona come dipendente; if (emp == null) ( Console.WriteLine("Conversione non riuscita"); ) else ( Console.WriteLine(emp.Company); )

Il secondo modo è catturare l'InvalidCastException che viene lanciata come risultato della conversione:

Persona persona = nuova Persona("Tom"); try ( Employee emp = (Dipendente)person; Console.WriteLine(emp.Company); ) catch (InvalidCastException ex) ( Console.WriteLine(ex.Message); )

Il terzo modo è verificare se la conversione è valida utilizzando la parola chiave is:

Persona persona = nuova Persona("Tom"); if(person is Employee) ( Employee emp = (Dipendente)person; Console.WriteLine(emp.Company); ) else ( Console.WriteLine("Conversione non consentita"); )

L'espressione persona è Dipendente verifica se la variabile persona è un oggetto di tipo Dipendente. Ma poiché in questo caso chiaramente non lo è, tale controllo restituirà false e la conversione non funzionerà.

Nella programmazione c'è spesso la necessità di eseguire calcoli su variabili di un tipo e di conseguenza ottenerne un'altra. Ad esempio, quando dividi numeri interi, ottieni un numero reale. Quando un valore di un tipo viene memorizzato in una variabile di un altro tipo, viene eseguita una conversione del tipo di dati. In C# questo è implementato da diversi meccanismi.

Conversione implicita del tipo di dati

Una conversione implicita si verifica quando un valore viene archiviato in una variabile di tipo diverso senza essere specificato nel codice.

Affinché il compilatore C# converta automaticamente un tipo di dati, devono essere vere due condizioni:

  • Il tipo valore e il tipo variabile devono essere compatibili tra loro;
  • L'intervallo dei possibili valori di un tipo di variabile non deve essere inferiore a quello di un tipo di valore.

Byte a = 15; byte b = 120; intc = a+b;

In questo esempio lo facciamo conversione implicita e la variabile c finirà per essere di tipo int. Ciò è possibile perché byte e int sono valori interi e il tipo int include completamente l'intervallo di byte.

Un altro esempio:

Breve a = 815; ushort b = a;//Errore

Anche se in questo caso il numero 815 è a portata breve apparirà un messaggio di errore. Ciò è dovuto al fatto che il compilatore per la conversione implicita controlla solo le condizioni di cui sopra e considera solo i tipi, senza prestare attenzione ai valori specifici.

Conversione esplicita del tipo di dati

Se le condizioni per una conversione implicita non sono soddisfatte, ma è necessario eseguire una conversione di tipo, viene utilizzato un cast di tipo. Questa è un'indicazione del tipo di destinazione in cui deve essere convertito il risultato del calcolo, scritta tra parentesi prima dell'espressione.

Intd = 13; int c = 4; var e = (doppio)d/c;

Pertanto, la variabile e avrà il tipo double e il valore 3,25. Se non utilizzassimo una conversione, questa variabile avrebbe un tipo int e un valore pari a 3 secondo le regole per la divisione intera in C#.

Un altro esempio:

Numero breve = 257; doppio doppio = 34,9318; int rnd = (breve) dbl; // Verrà assegnato il valore 34 byte what = (byte) num; // Verrà assegnato il valore 1

Nel caso di rnd, si applica la seguente regola: quando si convertono numeri in virgola mobile in numeri interi, la loro parte frazionaria viene scartata.

E nel caso di cosa tutto è un po' più complicato. Quando si esegue una conversione esplicita, il compilatore non presta attenzione agli intervalli di tipi. E durante l'esecuzione del programma, se si tenta di inserire un valore in una variabile che non è nel suo intervallo (con una profondità di bit maggiore), tutti i bit di ordine superiore vengono cancellati. Il numero 257 nella rappresentazione binaria breve appare come 00000001 00000001. Quando convertito in byte, rimane solo l'ultimo byte 00000000, cioè 1.

Una conversione in cui l'intervallo del tipo di variabile non copre completamente l'intervallo del tipo di valore è denominata conversione di restringimento. Per evitare la perdita di dati, come nell'esempio precedente, è necessario utilizzare un controllo di overflow.

Restringimento dell'overflow della conversione dei dati

Ovviamente non è possibile ignorare i punti del codice in cui potrebbe verificarsi la perdita di dati dovuta a overflow. In caso contrario, le variabili potrebbero assumere valori imprevisti, che influenzeranno il funzionamento del programma, e la causa dell'errore sarà abbastanza difficile da rintracciare.

Per impostazione predefinita, il verificarsi di un overflow viene ignorato. Per garantire che in questo caso venga sollevata un'eccezione appropriata, viene utilizzata la parola chiave check. Può essere posizionato prima di una determinata espressione o per designare con essa un blocco di codice. Quindi, quando si verifica un'eccezione, può essere gestita con il costrutto prova a prendere.

Casuale rnd = new Casuale(); int più grande = rnd.Next(99999); // Genera un numero casuale compreso tra 0 e 99999 più piccolo; try ( più piccolo = controllato((corto) più grande); ) catch (System.OverflowException e) ( Console.WriteLine('Overflow generato da controllato su più piccolo: ' + e.ToString()); // Stampa //un messaggio su che un'eccezione è stata gestita più piccola = -1; )

più grande è un numero casuale compreso tra 0 e 99999. Se questo valore supera l'intervallo del tipo short, verrà generata un'eccezione System.OverflowException e variabile più piccola verrà assegnato il valore -1. Se non si verifica alcun overflow, non ci sarà alcuna eccezione e la variabile più piccola assumerà semplicemente il valore della variabile più grande, ma nel tipo corto.

è operatore

Per verificare se è possibile eseguire il cast di un oggetto in un determinato tipo in C#, viene utilizzato l'operatore È. Controlla se un oggetto è un'istanza del tipo specificato stesso o un suo derivato. Il risultato di un'operazione binaria con l'operatore is è un valore booleano (vero o falso).

Un esempio di utilizzo dell'operatore is:

Class Samle1 () class Samle2 () : Sample1 () // Eredita la classe Sample1 class Sample3 () Samle1 t1 = new Samle1(); Campione2 t2 = nuovo Campione2(); Campione3 t3 = nuovo Campione3(); carattere t4 = 't'; if (t1 is Sample1) ( Console.WriteLine(“t1 is Sample1”); ) // Verrà stampato if (t2 is Sample1) ( Console.WriteLine(“t2 is Sample1”); ) // Verrà stampato if ( t3 è Esempio1) ( Console.WriteLine(“t3 è Esempio1”); ) // Non verrà stampato se (t4 è Esempio1) ( Console.WriteLine(“t4 è Esempio1”); ) // Non verrà stampato

Operatore come

L'operatore as viene utilizzato per convertire i tipi di riferimento compatibili. È da notare che se la conversione non è possibile, non viene lanciata un'eccezione, ma viene restituito null. Questo deve essere tenuto in considerazione durante l'elaborazione del risultato della conversione utilizzando as.

Oggetto Classe SamleClass() Arr = nuovo oggetto; Arr = new SampleClass(); Arr = “benvenuto”; Arr = (breve) 654; Arr = nullo; for (byte i = 0; i< Arr.Length; i++) { string t1 = Arr[i] as string; SampleClass t2 = Arr[i] as SampleClass; if (t1 != null) { Console.WriteLine(“{0}: it’s a string ‘” + t1 + “’”, i+1); } else if (t2 != null) { Console.WriteLine(“{0}: it’s a SampleClass”, i+1); } else { Console.WriteLine(“{0}: it’s not string or SampleClass”, i+1); } }

L'output dell'esempio sarebbe il seguente:

1: è una SampleClass

2: è una stringa "benvenuto"

3: non è una stringa o una SampleClass

4: non è una stringa o una SampleClass

Conversione di tipi utilizzando la classe Convert

La classe di sistema System.Convert contiene metodi che possono essere utilizzati per convertire valori di tipi di dati di base, nonché il tipo di sistema DateTime.

Convertire contiene una serie di metodi come Digitare, dove Type è sostituito dal nome di sistema del tipo di valore di destinazione (ad esempio ToChar, ToInt32, ToBoolean). Questi metodi consentono di eseguire tutte le possibili conversioni dai tipi C# di base.

Il metodo Convert.ChangeType converte qualsiasi oggetto in qualsiasi tipo specificato. Se si verifica una mancata corrispondenza o un overflow del tipo, il metodo genera un'eccezione.

I migliori articoli sull'argomento