Come configurare smartphone e PC. Portale informativo

C # conversione di tipo implicita. Conversioni al ribasso

Passiamo agli esempi. Classe test, contenente esempi, è un insieme di dati di diverso tipo, su cui vengono eseguite operazioni che illustrano le conversioni di tipo. Ecco la descrizione della classe

Test: utilizzando il sistema;
namespace TipiProgetto
{
test di classe pubblica{
/// < riepilogo>
/// un insieme di campi scalari di diverso tipo.
///
byte privato b= 255;
privato int x= 11 ;
privato uint ux= 1111 ;
galleggiante privato y= 5.5f;
doppia tinta privata= 5.55;
stringa privata s= "Ciao!";
stringa privata si= "25";
oggetto privato obj= nuovo oggetto ();
// I prossimi sono i metodi della classe, forniti lungo il percorso
// descrizioni di esempio
}
}

Il set di dati della classe include dati scalari tipo aritmetico variabili legate al valore tipo di stringa e digita oggetto, appartenenti a tipologie di riferimento. Considera un chiuso (privato) il metodo di questa classe è una procedura WholsChi con un argomento di classe formale Oggetto. La procedura stampa sulla console il nome dell'argomento passato, il tipo e il valore.

Ecco il suo testo:

/// < riepilogo>
/// Il metodo stampa le informazioni sul tipo sulla console e
/// il valore dell'argomento effettivo. Formale
/// l'argomento è di tipooggetto. L'argomento vero
/// può essere di qualsiasi tipo, da sempre
/// è consentita la conversione implicita in tipooggetto.
///
/// Nomesecondodiscussione
/// ammettiamodiscussionequalunquegenere
privato void WhoIsWho (nome stringa, oggetto qualsiasi){
Console.WriteLine ("tipo{0} è (1), il valore è{2}",
nome, any.GetType (), any.ToString ());
}

Ecco aperto (pubblico) metodo di classe test, in cui il metodo viene chiamato ripetutamente WholsChi con argomenti di diverso tipo:

/// < riepilogo>
/// ottieni informazioni sul tipo e sul valore
/// dell'argomento passato - variabile o espressione
/// riepilogo>
vuoto pubblico WhoTest (){
WholsWho ("x", x);
WholsWho ("ux", ux);
WhoIsWho ("y", y);
WhoIsWho ("dy", dy);
WhoIsWho ("s", s);
WhoIsWho ("11+ 5.55 + 5.5f ", 11+ 5.55 + 5.5f);
obj= 11 + 5.55 + 5.5f;
Chi è chi(" obj", obj);
}

Si noti che l'entità qualunque- argomento di classe formale Oggetto, che, ad ogni chiamata, cambia dinamicamente il tipo associandosi all'oggetto dato dall'argomento vero e proprio. Pertanto, il tipo dell'argomento segnalato alla console è il tipo dell'argomento effettivo. Nota anche che la classe ereditata dalla classe Oggetto metodo Gettype restituisce il tipo FCL, cioè il tipo che riflette il tipo del linguaggio e con il quale è reale lavori in corso durante l'esecuzione del modulo. Nella maggior parte delle chiamate, l'argomento effettivo è una variabile, la proprietà corrispondente della classe test, ma in un caso viene passata un'espressione aritmetica ordinaria, convertita automaticamente in un oggetto. Una situazione simile si verifica quando si esegue un incarico nella procedura in esame.

Nella fig. 11 mostra l'output alla console quando è stato chiamato il metodo ChiTest nella procedura di cui sopra Principale classe Classi.

Figura 11. Stampa dei risultati del test WhoTest

Dove, come e quando vengono eseguite le conversioni di tipo?

La necessità di conversione del tipo sorge in espressioni, assegnazioni, sostituzione di argomenti di metodi formali con quelli reali.

Se, durante la valutazione di un'espressione, gli operandi di un'operazione hanno tipi diversi, diventa necessario eseguirne il cast allo stesso tipo. Tale necessità sorge anche quando gli operandi sono dello stesso tipo, ma non è coerente con il tipo dell'operazione. Ad esempio, quando si eseguono addizioni, operandi di tipo byte deve essere lanciato per digitare int, poiché l'addizione non è definita sui byte. Quando si esegue un incarico X= e tipo di fonte e e tipo di bersaglio X deve essere coerente. Allo stesso modo, quando si chiama un metodo, anche i tipi di origine e destinazione degli argomenti effettivi e formali devono essere coerenti.

Conversioni del tipo di riferimento

Poiché le operazioni sui tipi di riferimento non sono definite (l'eccezione sono le stringhe, ma le operazioni su di esse, inclusa l'assegnazione, vengono eseguite come sui tipi di valore), la loro necessità sorge solo durante le assegnazioni e le chiamate di metodo.

Digitare le conversioni nelle espressioni

In C#, tali conversioni sono divise in implicite ed esplicite. Le conversioni implicite sono quelle conversioni il cui risultato ha sempre successo e non comporta una perdita di accuratezza dei dati. Le conversioni implicite vengono eseguite automaticamente. Per i dati aritmetici, ciò significa che nelle conversioni implicite, l'intervallo del tipo di destinazione contiene l'intervallo tipo originale... Ad esempio, una conversione da type byte nel tipo int si riferisce a implicito perché l'intervallo è come byteè un sottoinsieme dell'intervallo int. Questa conversione ha sempre successo e non può comportare una perdita di precisione.

Le conversioni esplicite sono conversioni legali la cui riuscita non è garantita o può comportare una perdita di precisione. Tali conversioni potenzialmente pericolose devono essere specificate esplicitamente dal programmatore. Conversione da tipo int nel tipo byte si riferisce a esplicito perché non è sicuro e può portare alla perdita di cifre significative. Nota che non tutti i tipi hanno conversioni esplicite. In questo caso sono necessari altri meccanismi di conversione del tipo, che verranno discussi in seguito.

Conversioni all'interno di un tipo aritmetico

Il tipo aritmetico, come mostrato nella tabella dei tipi di dati, si divide in 11 sottotipi. Nella fig. 12 mostra un diagramma delle conversioni all'interno di un tipo aritmetico.

Figura 12. Gerarchia delle conversioni all'interno di un tipo aritmetico

Lo schema riportato in figura permette di rispondere ad una serie di importanti quesiti legati all'esistenza di conversioni tra tipi. Se il diagramma mostra un percorso (frecce) dal tipo A al tipo B, significa che esiste una conversione implicita dal tipo A al tipo B. Tutte le altre conversioni tra sottotipi di tipo aritmetico esistono, ma sono esplicite. Si noti che non ci sono cicli nel diagramma, tutte le frecce sono unidirezionali, quindi la conversione da inversa a implicita deve essere sempre specificata in modo esplicito.

Il percorso mostrato nel diagramma può essere piuttosto lungo, ma ciò non significa che l'intera sequenza di trasformazioni venga eseguita su questo percorso... La presenza di un percorso indica solo l'esistenza di una conversione implicita e la conversione stessa viene eseguita una sola volta, dal tipo di origine A al tipo di destinazione B.

A volte si verifica una situazione in cui per un tipo di fonte possono esistere più tipi di destinazioni contemporaneamente ed è necessario selezionare un obiettivo: il tipo di destinazione. Tali problemi di selezione sorgono, ad esempio, quando si lavora con metodi sovraccaricati nelle classi.

La regola per la scelta di un'implementazione quando si chiama un metodo è la seguente: viene selezionata l'implementazione per la quale il percorso di trasformazione specificato nel diagramma è più breve. Se c'è una corrispondenza esatta dei parametri per tipo (percorso di lunghezza 0), allora, ovviamente, verrà scelta questa implementazione.

Diamo un'occhiata a un altro caso di prova. in classe testè incluso un gruppo di metodi sovraccaricati OCarica con uno e due argomenti. Questi metodi sono:

/// < riepilogo>
/// Gruppo di metodi sovraccaricatiOCarica
/// con uno o due argomenti di tipo aritmetico.
/// Se l'argomento effettivo è uno, allora uno dei
/// metodi che più si avvicinano al tipo dell'argomento.
/// Quando si chiama un metodo con due argomenti, è possibile
/// Conflitto nella scelta di un metodo appropriato, con conseguente
/// a un errore in fase di compilazione.
///
vuoto privato OLoad (float par){
Console.WriteLine ("valore mobile{0}", par);
}
/// < riepilogo>
/// Metodo sovraccaricoOCaricacon un parametro di tipolungo
///
///
vuoto privato OLoad (par lungo){
Console.WriteLine ("valore lungo (0)", par);
}
/// < riepilogo>
/// Metodo sovraccaricoIn caricacon un parametro di tipoulong
///
///
privato void OLoad (ulong par){
Console.WriteLine ("valore ulong (0)", par);
}
/// < riepilogo>
/// Metodo sovraccaricoOCaricacon un parametro di tipoDoppio
///
///
vuoto privato OnLoad (doppio par){
Console.WriteLine ("doppio valore (0)", par);
}
/// < riepilogo>
/// Metodo sovraccaricoOCaricacon due parametri comelungoelungo
///
///
///
private void OLoad (lungo par1, lungo par2){
Console.WriteLine ("par1 lungo{0}, lungo par2{1}", par1, par2);
}
/// < riepilogo>
/// Metodo sovraccaricoOCaricacon due parametri come
/// DoppioeDoppio
///
///
///
vuoto privato OLoad (doppio par1, doppio par2){
Console.WriteLine ("doppio par1{0}, doppio par2{1}", par1, par2);
}
/// < riepilogo>
/// Metodo sovraccaricoOCaricacon due parametri come
/// integalleggiante
///
///
///
private void OLoad (int par1, float par2){
Console.WriteLine ("int par1{0}, flottante par2{1}", par1, par2);
}

Tutti questi metodi sono abbastanza semplici. Forniscono informazioni sul tipo e sul valore degli argomenti passati.

Ecco una procedura di test che chiama il metodo OCarica con diverso numero e tipo di argomenti:

/// < riepilogo>
/// Chiamare un metodo sovraccaricoOCarica. Dipende da
/// tipo e numero di argomenti viene chiamato uno dei metodi del gruppo.
///
public void OLoadTest (){
OCarica (x);
OLoad (ux);
OLoad (y);
OLoad (dy);
// OLoad (x, ux);
// conflitto: (int, float)e(lungo lungo)
OLoad (x, (float) ux);
OLoad (y, dy);
OCarica(X, dy);
}

Si noti che una delle chiamate è commentata poiché porta a un conflitto durante la fase di traduzione. Per eliminare il conflitto quando si chiama il metodo, abbiamo dovuto specificare una conversione esplicita dell'argomento, che viene mostrata nella riga che segue la riga del commento. Risultato della prova OLoadTestè mostrato in Fig. tredici.

Figura 13. Stampa dei risultati di OLoadTest

Conversioni esplicite

Come accennato in precedenza, le conversioni esplicite possono essere pericolose a causa della perdita di precisione. Pertanto, vengono eseguiti sotto la direzione del programmatore: ha tutta la responsabilità dei risultati.

Conversioni di stringhe

Una classe importante di conversioni sono le conversioni in stringa e viceversa. Le conversioni a un tipo stringa sono sempre definite, poiché tutti i tipi sono discendenti della classe base Oggetto, e, quindi, avere il metodo Accordare(). È stata definita un'implementazione adeguata di questo metodo per i tipi incorporati. In particolare, per tutti i sottotipi di tipo aritmetico, il metodo Accordare() restituisce in forma opportuna una stringa specificando il corrispondente valore aritmetico. Nota, il metodo Accordare può essere chiamato in modo esplicito, ma se non viene specificata una chiamata esplicita, verrà chiamata implicitamente, ogni volta che il contesto richiede una conversione in un tipo stringa. Ecco un esempio pertinente:

/// < riepilogo>
/// Dimostrazione della conversione di dati di vario tipo in una stringa.
///
public void ToStringTest ()
{
S= " VladimirPetrov ";
s1= " Età: ";
ux= 27;
S= S+ s1+ ux.ToString();
s1= " Stipendio: ";
dy= 2700.50;
S= S+ s1+ morire;
Chi è chi(" S", S);
}

Il risultato di questa procedura è mostrato in Fig. 14.

Figura 14. Stampa dei risultati di ToStringTest

Le conversioni da un tipo stringa ad altri tipi, ad esempio l'aritmetica, devono essere eseguite in modo esplicito. Ma non ci sono conversioni esplicite tra aritmetica e stringhe. Sono necessari altri meccanismi, disponibili in C#. A questo scopo, puoi usare i metodi di classe corrispondenti Convertire Libreria FCL incorporata nello spazio dei nomi Sistema. Facciamo un esempio:

/// < riepilogo>
/// Dimostrazione della conversione di una stringa in dati di vario tipo.
///
public void FromStringTest (){
S= " accedereetà ";
Console.WriteLine(s);
s1= Console.ReadLine ();
ux= Convert.ToUInt32 (s1);
Chi è chi("Età: ",ux);
S= "Inserisci stipendio";
Console.WriteLine(s);
s1= Console.ReadLine ();
dy= Convert.ToDouble (s1);
Chi è chi ("Stipendio: ", dy);
}

Questo esempio mostra l'input di dati dalla console tipi diversi... Dati letti dalla console per metodo Linea di lettura o Leggi, rappresentano sempre una stringa, che deve poi essere convertita nel tipo desiderato. Per questo, vengono chiamati i metodi di classe corrispondenti. Convertire. Naturalmente, affinché la conversione vada a buon fine, la stringa deve contenere un valore in un formato che consenta tale conversione. Si noti, ad esempio, che quando si scrive il valore di un numero, è necessario utilizzare una virgola, non un punto, per evidenziare la parte frazionaria; in caso contrario, si verificherà un errore di runtime.

Nella fig. 15 mostra i risultati dell'output e dell'input dalla console quando questa procedura è in esecuzione.

Figura 15. Stampa dei risultati del FromStringTest

La conversione implicita del tipo di dati viene eseguita dal compilatore C++, mentre la conversione esplicita del tipo di dati viene eseguita dal programmatore stesso. Sulla conversione del tipo di dati dirò quanto segue: "Il risultato di qualsiasi calcolo verrà convertito nel tipo di dati più accurato di quei tipi di dati coinvolti nel calcolo". Per esempio illustrativo Presenterò una tabella con le conversioni del tipo di dati. Diamo un'occhiata all'operazione di divisione nella tabella. Come tipo di dati intero, prendiamo int, beh, avremo un tipo di dati reale galleggiante.

Tabella 1 - Conversione esplicita e implicita del tipo di dati in C++
X Risultato di 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

La tabella mostra che cambiando le variabili in luoghi diversi, il risultato rimane lo stesso (nel nostro caso, questo è il dividendo e il divisore). Riguarda la conversione implicita del tipo di dati. Per quanto riguarda la conversione esplicita, è necessario 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 tali numeri 15 e 2, dividiamo! 15/2 = 7. Il risultato è lo stesso della tabella. Ma se fai trasformazioni minori, ad esempio: 15,0 / 2 = 7,5 con questa divisione, il numero 15 è reale, quindi il risultato sarà reale. Il numero 15 stesso non è cambiato dal punto di vista della matematica, perché 15 = 15,0. La stessa tecnica potrebbe essere applicata a due, il risultato sarebbe lo stesso, ma potrebbe essere applicata a due numeri contemporaneamente, ma perché, se uno dei due è sufficiente.

Un altro modo per convertire in modo esplicito i tipi di dati:

Float (15) / 2 // il risultato è 7.5, il numero 15 viene convertito nel tipo di dati reale float. double (15) / 2 // il risultato è 7.5 - lo stesso !!!

C++ fornisce anche operazione unaria cast di tipo:

Static_cast(/ * variabile o numero * /)

esempio: static_cast (15) / 2 il risultato è 7.5
Esempio con una variabile:

Int ret = 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 conversione esplicita e implicita dei tipi di dati.

// pryeobrazovanie.cpp: definisce il punto di ingresso per l'applicazione console. #include "stdafx.h" #include #includere usando 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 float_value15 = 15, float_value2 = 2; // dichiara due variabili 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; }

V linea 5 collegato , questa libreria è necessaria per utilizzare vari manipolatori, nel nostro caso - setprecision fisso (). V linea 10due appositamente creati variabili come int , allo stesso modo ha creato due variabili di tipo galleggiare dentro linea 11, queste variabili saranno necessarie per convertire i loro valori in altri tipi di dati. Vlinea 12dopo l'operatore cout e spostare le operazioni sul flusso di output << ci sono due manipolatori fixed e setprecision(). Manipolatore fisso - questo non è un manipolatore parametrizzato, poiché non accetta alcun parametro, viene scritto senza parentesi. Questo manipolatore viene utilizzato in combinazione con un manipolatore parametrizzato setprecision () ed esegue una visualizzazione fissa delle cifre decimali. un manipolatore setprecision () visualizza il numero di posizioni decimali e quello indicato tra parentesi. Vlinee 13, 14, 15, 16vengono mostrati esempi di conversione implicita del tipo di dati, questi esempi sono presi daTabella 1... V linee 17, 18mostra uno dei modi per trasformare in modo esplicito i dati. L'essenza di questo metodo è che è necessario aggiungere una virgola e zero a un numero intero. Vlinee 19, 20la conversione esplicita viene eseguita utilizzando i tipi castable come funzioni, all'interno delle quali è necessario specificare il valore o la variabile da convertire. Nelle righe 21, 22, 23, viene eseguita una conversione di tipo di dati esplicita utilizzando un'operazione di conversione di dati unari. Le parentesi indicano la variabile o il valore da convertire e i caratteri sono incorniciati < > il tipo di dati in cui convertire. Di seguito è mostrato un esempio di come funziona il programma (vedi Figura 1).

Figura 1 - Conversione esplicita e implicita di tipi di dati C++

V 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 è il tipo di dati per l'archiviazione. Quindi, da Figura 1 puoi vedere che ci sono dei simboli alla fine. Questi caratteri sono stati ottenuti convertendo i numeri in caratteri. I numeri erano codici da. Pertanto, se è necessario visualizzare qualsiasi carattere dalla tabella ASCII, è possibile farlo come mostrato in linee 22, 23, sostituendo solo il codice richiesto.

Nella programmazione, è spesso necessario eseguire calcoli su variabili di un tipo e, di conseguenza, ottenerne un altro. Ad esempio, quando dividi numeri interi, ottieni un valore reale. Quando un valore di un tipo viene archiviato in una variabile di un altro tipo, viene eseguita una conversione del tipo di dati. Ci sono diversi meccanismi per questo in C #.

Conversione implicita del tipo di dati

La conversione implicita si verifica quando un valore viene archiviato in una variabile di tipo diverso senza specificarlo nel codice.

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

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

Byte a = 15; byte b = 120; int c = a + b;

Questo esempio funziona conversione implicita , e la variabile c alla fine sarà di tipo int. Ciò è possibile perché byte e int sono numeri interi e int contiene l'intero intervallo di byte.

Un altro esempio:

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

Anche se 815 è nel raggio d'azione più corto, in questo caso apparirà un messaggio di errore... Ciò è dovuto al fatto che il compilatore per la conversione implicita controlla solo le condizioni di cui sopra e guarda solo i tipi, senza prestare attenzione a valori specifici.

Conversione esplicita del tipo di dati

Se le condizioni di conversione implicita non vengono soddisfatte, ma è necessario eseguire la conversione del tipo, viene utilizzato il cast del tipo. Questa è un'indicazione del tipo di destinazione in cui convertire il risultato del calcolo, scritto tra parentesi prima dell'espressione.

Int d = 13; intero c = 4; var e = (doppio) d / c;

Pertanto, la variabile e riceverà il tipo double e il valore 3.25. Se non usassimo la conversione, questa variabile avrebbe il tipo int e il valore 3 secondo le regole per la divisione degli interi in C #.

Un altro esempio:

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

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

E nel caso di cosa? tutto è un po' più complicato. Durante la conversione esplicita, il compilatore ignora gli intervalli di tipi. E durante l'esecuzione del programma, se si tenta di immettere in una variabile un valore che non rientra nel suo intervallo (con una profondità di bit maggiore), tutti i bit di ordine superiore vengono cancellati. Il numero 257 nella rappresentazione binaria del tipo ushort è simile a 00000001 00000001. Quando viene convertito in byte, rimane solo l'ultimo byte 00000000, ovvero 1.

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

Overflow durante il restringimento della conversione dei dati

Ovviamente, non puoi ignorare i punti nel codice in cui può verificarsi la perdita di dati a causa dell'overflow. In caso contrario, le variabili potrebbero assumere valori imprevisti, il che influenzerà il funzionamento del programma e la causa dell'errore sarà piuttosto difficile da rintracciare.

Per impostazione predefinita, le occorrenze di overflow vengono ignorate. La parola chiave selezionata viene utilizzata per attivare un'eccezione appropriata in questo caso. Può essere posizionato davanti a un'espressione specifica oppure puoi designare un blocco di codice con esso. Inoltre, quando si verifica un'eccezione, può essere elaborata con la costruzione prova a prendere.

Casuale rnd = nuovo 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 è stata gestita un'eccezione più piccola = -1;)

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

è operatore

Per verificare la possibilità di eseguire il casting di un oggetto di un certo tipo in C#, utilizzare l'operatore è... Controlla se un oggetto è un'istanza del tipo specificato stesso o se ne deriva. 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 è Campione1) (Console.WriteLine ("t1 è Campione1");) // Verrà visualizzato se (t2 è Campione1) (Console.WriteLine ("t2 è Campione1");) // Verrà visualizzato se ( t3 è Sample1) (Console.WriteLine ("t3 è Sample1");) // Non verrà visualizzato se (t4 è Sample1) (Console.WriteLine ("t4 è Sample1");) // Non verrà visualizzato

Come operatore

L'operatore as viene utilizzato per convertire i tipi di riferimento compatibili. Si noti che se la conversione fallisce, non viene generata alcuna eccezione, ma viene restituito null. Questo deve essere preso in considerazione quando si elabora il risultato della conversione con as.

Classe SamleClass() oggetto 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 di esempio sarà il seguente:

1: è una SampleClass

2: è "una stringa" benvenuto "

3: non è stringa o SampleClass

4: non è una stringa o SampleClass

Conversione di tipi con la classe Convert

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

Convertire contiene un insieme di metodi della forma 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 conversioni possibili ai tipi C# di base.

Il metodo Convert.ChangeType converte qualsiasi oggetto in qualsiasi tipo specificato. Il metodo genera un'eccezione in caso di mancata corrispondenza o overflow del tipo.

Nella programmazione, non è raro che i valori delle variabili di un tipo vengano assegnati a variabili di un altro tipo. Ad esempio, nel frammento di codice seguente, un valore intero come int assegnato a una variabile in virgola mobile di tipo galleggiante:
int io;galleggiante f;io = 10;f = io;

Se in un'operazione le assegnazioni sono miste compatibile tipi di dati, il valore a destra dell'operatore di assegnazione viene automaticamente convertito nel tipo specificato a sinistra. Pertanto, nel frammento di codice sopra, il valore della variabile io prima convertito in tipo galleggiante e poi assegnato a una variabile F.

La domanda è: la conversione del tipo è sempre possibile? Quando appariranno i messaggi di errore, come influirà sull'affidabilità dei programmi sviluppati?

A causa della tipizzazione forte, non tutti i tipi di dati in C# sono completamente compatibili e, pertanto, non tutte le conversioni di tipo sono consentite implicitamente.

Ad esempio, i tipi bool e int non sono compatibili. È vero, la conversione di tipi incompatibili può ancora essere eseguita da portando. Lancio significa essenzialmente convertirli esplicitamente.

Conversione automatica del tipo

Quando i dati di un tipo vengono assegnati a una variabile di un altro tipo, conversione implicita tipi accade automaticamente alle seguenti condizioni:
1) entrambi i tipi sono compatibili;
2) l'intervallo di rappresentazione dei numeri del tipo di destinazione è più ampio di quello del tipo originale.
Se entrambe queste condizioni sono soddisfatte, allora ampliamento trasformare.
Ad esempio, il tipo int abbastanza grande da contenere tutti i valori validi di tipo byte, e inoltre, entrambi i tipi, int e byte, sono tipi interi compatibili e quindi la conversione implicita è del tutto possibile per loro.
I tipi numerici, sia interi che in virgola mobile, sono abbastanza compatibili tra loro per eseguire conversioni di ampliamento.

Consideriamo un esempio:

utilizzando il sistema; namespace ConsoleApplication1 (classProgram (static void Main (string args) (short num1, num2; num1 = 10; num2 = 15; Console.WriteLine ("(0) + (1) = (2)", num1, num2, Sum ( num1, num2)); Console.ReadLine ();) staticintSum (int x, int y) (return x + y;)))

prestare attenzione a che il metodo Sum() si aspetta due parametri int. Tuttavia, nel metodo Main(), vengono effettivamente passate due variabili di tipo short. Sebbene ciò possa sembrare una mancata corrispondenza di tipo, il programma verrà compilato ed eseguito senza errori e restituirà 25 come previsto.
Il motivo per cui il compilatore considererà questo codice sintatticamente corretto è perché la perdita di dati è impossibile qui.
Poiché il valore massimo (32767) che uno short può contenere è ben compreso nell'intervallo di un int (il cui valore massimo è 2147483647), il compilatore espanderà implicitamente ogni short in un int.
Formalmente, il termine "estensione" è usato per denotare un implicito lancio verso l'alto ( lancio verso l'alto), che non comporta la perdita di dati.

Casting di tipi incompatibili

Sebbene le conversioni implicite siano utili, non soddisfano tutte le esigenze di programmazione perché consentono solo conversioni ampliate di tipi compatibili. E in tutti gli altri casi, devi ricorrere alla conversione del tipo. Il cast è un comando al compilatore per convertire il risultato della valutazione di un'espressione in un tipo specificato. Ciò richiede una conversione di tipo esplicita.

La seguente è la forma generale di typecasting:
(target_type) espressione
Qui target_type denota il tipo in cui si desidera convertire l'espressione specificata.

Se il casting risulta in restringimento trasformazione, alcune informazioni potrebbero andare perse. Ad esempio, a seguito del casting dal tipo long al tipo int, alcune informazioni vengono perse se il valore di tipo long risulta essere maggiore dell'intervallo di rappresentazione dei numeri per il tipo int, poiché i bit più significativi di questo valore numerico vengono scartati.
Quando viene eseguito il cast di un valore in virgola mobile su un tipo intero, la parte frazionaria di questo valore numerico viene persa a causa del troncamento. Quindi, se assegni il valore 1.23 a una variabile intera, di conseguenza solo la parte intera del numero originale (1) rimarrà in essa e la sua parte frazionaria (0,23) andrà persa.

Facciamo un esempio:

utilizzando il sistema; namespace ConsoleApplication1 (classProgram (static void Main (string args) (int i1 = 455, i2 = 84500; decimal dec = 7.98845m; // Trasmetti due numeri int al tipo short Console.WriteLine ((short) i1); Console. WriteLine ((short) i2); // Trascina un decimale in int Console.WriteLine ((int) dec); Console.ReadLine ();)))

Il risultato di questo programma sarà:
455
18964
7

Si prega di notare che la variabile i1 è stata convertita correttamente nel tipo short, poiché il suo valore è compreso nell'intervallo di questo tipo di dati. La conversione di dec in int ha restituito la parte intera di quel numero. Conversione della variabile i2 restituita valore di overflow 18964 (cioè 84500 - 2 * 32768).

Il ruolo della classe System.Convert

Alla fine dell'argomento della conversione dei tipi di dati, vale la pena notare che nello spazio dei nomi Sistema c'è Converti classe, che può essere utilizzato anche per espandere e restringere i dati:
byte sum = Convert.ToByte (var1 + var2);

Uno dei vantaggi di un approccio basato sulla classe System.Convertè dovuto al fatto che consente conversioni tra tipi di dati in modo indipendente dal linguaggio.

Tuttavia, poiché C # ha un'operazione di conversione esplicita, utilizzando la classe Convertire convertire i tipi di dati è solitamente una questione di gusti.

Un altro scopo utile dei metodi di classe Convertire consiste nel convertire una variabile stringa in una variabile numerica. Lo uso abbastanza spesso! Infatti, in un'applicazione console, è possibile solo l'input di stringhe e poiché l'operatore Console.ReadLine() restituisce una stringa, quindi può essere ulteriormente convertita in un numero utilizzando il metodo appropriato, ad esempio:
int k = Convert.ToInt32 (Console.ReadLine ());
Se è impossibile convertire una stringa in un numero, si verifica un'eccezione (di seguito l'eccezione - eccezione), che può anche essere elaborato.

Passiamo all'apprendimento degli operatori C# e inizieremo con.

Conversioni di tipo

Nella programmazione, non è raro che i valori delle variabili di un tipo vengano assegnati a variabili di un altro tipo. Ad esempio, nel seguente frammento di codice, un int viene assegnato a un float:

Int io; galleggiante f; io = 10; f = io; // assegna un valore intero a una variabile float

Se i tipi di dati compatibili vengono mischiati in un'operazione di assegnazione, il valore a destra dell'operatore di assegnazione viene automaticamente convertito nel tipo indicato a sinistra. Pertanto, nel frammento di codice sopra, il valore di i viene prima convertito in float e quindi assegnato a f. Tuttavia, a causa del rigoroso controllo del tipo, non tutti i tipi di dati in C# sono completamente compatibili e, pertanto, non tutte le conversioni di tipo sono consentite in modo implicito. Ad esempio, i tipi bool e int non sono compatibili. È vero, la conversione di tipi incompatibili può ancora essere eseguita da portando... Typecasting significa essenzialmente convertirli in modo esplicito.

Conversione automatica del tipo

Quando i dati di un tipo vengono assegnati a una variabile di un altro tipo, conversione implicita type si verifica automaticamente nelle seguenti condizioni:

  • entrambi i tipi sono compatibili
  • l'intervallo di rappresentazione dei numeri del tipo di destinazione è più ampio di quello del tipo originale

Se entrambe queste condizioni sono soddisfatte, allora ampliamento trasformare... Ad esempio, int è abbastanza grande da contenere tutti i valori validi di byte e, inoltre, sia int che byte sono tipi interi compatibili, e quindi la conversione implicita è del tutto possibile per loro.

I tipi numerici, sia interi che in virgola mobile, sono abbastanza compatibili tra loro per eseguire conversioni di ampliamento. Consideriamo un esempio:

Utilizzo del sistema; utilizzando System.Collections.Generic; utilizzando System.Linq; utilizzando System.Text; namespace ConsoleApplication1 (class Program (static void Main (string args) (short num1, num2; num1 = 10; num2 = 15; Console.WriteLine ("(0) + (1) = (2)", num1, num2, Sum (num1, num2)); Console.ReadLine ();) static int Sum (int x, int y) (return x + y;)))

Si noti che il metodo Sum() prevede l'arrivo di due parametri int. Tuttavia, nel metodo Main(), vengono effettivamente passate due variabili di tipo short. Sebbene ciò possa sembrare una mancata corrispondenza di tipo, il programma verrà compilato ed eseguito senza errori e restituirà 25 come previsto.

Il motivo per cui il compilatore considererà questo codice sintatticamente corretto è perché la perdita di dati è impossibile qui. Poiché il valore massimo (32767) che uno short può contenere è ben compreso nell'intervallo di un int (il cui valore massimo è 2147483647), il compilatore espanderà implicitamente ogni short in un int. Formalmente, il termine "estensione" viene utilizzato per indicare un cast implicito verso l'alto che non comporta la perdita di dati.

Casting di tipi incompatibili

Sebbene le conversioni implicite siano utili, non soddisfano tutte le esigenze di programmazione perché consentono solo conversioni ampliate di tipi compatibili. E in tutti gli altri casi, devi ricorrere alla conversione del tipo. portandoè un comando al compilatore per convertire il risultato della valutazione di un'espressione nel tipo specificato. Ciò richiede una conversione di tipo esplicita. La seguente è la forma generale di typecasting:

(target_type) espressione

Qui target_type denota il tipo in cui si desidera convertire l'espressione specificata.

Se il casting risulta in restringimento trasformazione, alcune informazioni potrebbero andare perse. Ad esempio, a seguito del casting dal tipo long al tipo int, alcune informazioni vengono perse se il valore di tipo long risulta essere maggiore dell'intervallo di rappresentazione dei numeri per il tipo int, poiché i bit più significativi di questo valore numerico vengono scartati. Quando viene eseguito il cast di un valore in virgola mobile su un valore intero, la parte frazionaria di questo valore numerico viene persa a causa del troncamento. Quindi, se assegni il valore 1.23 a una variabile intera, di conseguenza solo la parte intera del numero originale (1) rimarrà in essa e la sua parte frazionaria (0,23) andrà persa. Facciamo un esempio:

Utilizzo del sistema; utilizzando System.Collections.Generic; utilizzando System.Linq; utilizzando System.Text; namespace ConsoleApplication1 (class Program (static void Main (string args) (int i1 = 455, i2 = 84500; decimal dec = 7.98845m; // Lancia due numeri di tipo int // per digitare short Console.WriteLine ((short) i1” ); Console.WriteLine ((short) i2); // Trascina un // tipo decimale a int Console.WriteLine ((int) dec); Console.ReadLine ();)))

Il risultato di questo programma sarà:

Si prega di notare che la variabile i1 è stata convertita correttamente nel tipo short, poiché il suo valore è compreso nell'intervallo di questo tipo di dati. La conversione di dec in int ha restituito la parte intera di quel numero. Conversione della variabile i2 restituita valore di overflow 18964 (cioè 84500 - 2 * 32768).

Intercettazione di restringimento delle trasformazioni dei dati

Nell'esempio precedente, lanciare la variabile i2 a short non è accettabile, poiché sorge perdita di dati... C# suggerisce parole chiave come controllato e deselezionato per garantire che la perdita di dati non passi inosservata.

Per impostazione predefinita, quando non viene intrapresa alcuna azione correttiva appropriata, le condizioni di overflow e underflow si verificano senza errori. Esistono due modi per gestire le condizioni di overflow e underflow nell'applicazione. Questo può essere fatto manualmente facendo affidamento sulle tue conoscenze e abilità di programmazione.

Lo svantaggio di questo approccio è che anche nel caso di applicare i massimi sforzi, una persona rimane comunque una persona e alcuni errori possono sfuggire ai suoi occhi.

Fortunatamente, C# fornisce la parola chiave selezionata. Quando un'istruzione (o un blocco di istruzioni) è racchiusa in un contesto controllato, il compilatore C# genera istruzioni CIL aggiuntive per verificare le condizioni di overflow che possono derivare da addizione, moltiplicazione, sottrazione o divisione di due tipi di dati numerici.

Se si verifica una condizione di overflow in fase di esecuzione, verrà generata un'eccezione System.OverflowException... Diamo un'occhiata a un esempio in cui invieremo il valore dell'eccezione alla console:

Utilizzo del sistema; utilizzando System.Collections.Generic; utilizzando System.Linq; utilizzando System.Text; namespace ConsoleApplication1 (class Program (static void Main (string args) (byte var1 = 250; byte var2 = 150; try (byte sum = verificato ((byte) (var1 + var2))); Console.WriteLine ("Sum: (0 ) ", sum);) catch (OverflowException es) (Console.WriteLine (es.Message); Console.ReadLine ();))))

Il risultato di questo programma:

Imposta un controllo a livello di progetto per le condizioni di overflow

Se stai creando un'applicazione in cui l'overflow non dovrebbe mai passare inosservato, potresti scoprire che avvolgere con la parola chiave selezionata è un numero fastidiosamente elevato di righe di codice. In tal caso, in alternativa, il compilatore C# supporta bandiera / spuntato... Quando questo flag è attivato, tutte le operazioni aritmetiche nel codice verranno automaticamente controllate per eventuali overflow, senza utilizzare la parola chiave check per ciascuna di esse. Analogamente, il rilevamento dell'overflow comporta la generazione dell'eccezione corrispondente in fase di esecuzione.

Per attivare questo flag in Visual Studio 2010, aprire la pagina delle proprietà del progetto, andare nella scheda Build, fare clic sul pulsante Avanzate e selezionare la casella nella finestra di dialogo che si apre Verificare l'overflow/underflow aritmetico:

È importante notare che C# fornisce la parola chiave deselezionato, che consente di disabilitare il lancio di un'eccezione di overflow nei singoli casi.

Quindi, per riassumere l'uso delle parole chiave selezionate e non selezionate in C#, si noti che per impostazione predefinita, l'overflow aritmetico viene ignorato nel runtime .NET. Se è necessario elaborare singoli operatori, è necessario utilizzare la parola chiave selezionata e, se è necessario rilevare tutti gli errori relativi all'overflow nell'applicazione, è necessario attivare il flag / verificato. Per quanto riguarda la parola chiave unchecked, può essere utilizzata quando è presente un blocco di codice in cui l'overflow è legale (e quindi non dovrebbe comportare la generazione di un'eccezione in fase di esecuzione).

Principali articoli correlati