Domanda

In Jesse Liberty di Apprendimento di C# libro, dice: "gli Oggetti di un tipo possono essere convertiti in oggetti di altro tipo.Questo è chiamato il casting".

Se si analizza il generati dal codice riportato di seguito, si può vedere chiaramente che la fusione di assegnazione non fa la stessa cosa, come convertito assegnazione.Nel primo caso, si può vedere il boxing/unboxing che si verificano;in quest'ultimo è possibile vedere una chiamata a un metodo di conversione.

So che alla fine potrebbe essere solo una stupida semantica differenza-ma il casting è solo un'altra parola per la conversione.Non voglio dire di essere un po ' bisbetica, ma io non sono interessato a nessuno gut feeling su questo--opinioni non contano qui!Chiunque può scegliere un riferimento definitivo che conferma o nega se la fusione e la conversione sono la stessa cosa?

    object x;
    int y;

    x = 4;

    y = ( int )x;

    y = Convert.ToInt32( x );

Grazie

rp

Nota aggiunta dopo Matt commento su esplicita/implicita:

Non credo implicito/esplicito è la differenza.Nel codice che ho postato, il cambiamento è esplicito in entrambi i casi.Una conversione implicita è quello che si verifica quando si assegna un breve int.

Nota per Sklivvz:

Volevo la conferma che il mio sospetto di la scioltezza di Jesse Liberty (altrimenti di solito lucido e chiaro) lingua era corretta.Ho pensato che Jesse Liberty di essere un po ' sciolto con la sua lingua.Capisco che la fusione è indirizzato nella gerarchia di oggetti--cioè, non può essere lanciata da un intero in una stringa, ma si potrebbe cast di eccezione personalizzata derivato dal Sistema.Eccezione per un Sistema.Fa eccezione.

È interessante, però, che quando si tenta di gettare da un int in una stringa il compilatore ti dice che non si riusciva a "convertire" il valore.Forse Jesse è più corretto di quello che pensavo!

È stato utile?

Soluzione

La semplice risposta è: dipende.

Per i tipi di valore, il casting comporterà una vera conversione in un altro tipo. Ad esempio:

float f = 1.5f;
int i = (int) f; // Conversion

Quando l'espressione di casting viene decompressa, il risultato (supponendo che funzioni) è di solito solo una copia di ciò che era nella casella, con lo stesso tipo. Ci sono eccezioni, tuttavia: è possibile decomprimere da un int box a un enum (con un tipo di int sottostante) e viceversa; allo stesso modo puoi decomprimere da un int boxed a un Nullable < int > ;.

Quando l'espressione di casting proviene da un tipo di riferimento a un altro e non è coinvolta alcuna conversione definita dall'utente, non c'è conversione per quanto riguarda l'oggetto stesso - solo il tipo di riferimento quot;! modifiche <> quot; - e questo è solo il modo in cui viene considerato il valore, piuttosto che il riferimento stesso (che sarà gli stessi bit di prima). Ad esempio:

object o = "hello";
string x = (string) o; // No data is "converted"; x and o refer to the same object

Quando vengono coinvolte conversioni definite dall'utente, questo solitamente comporta la restituzione di un oggetto / valore diverso. Ad esempio, potresti definire una conversione in stringa per il tuo tipo - e  questo non sarebbe certamente lo stesso dato del tuo oggetto. (Potrebbe trattarsi di una stringa esistente a cui fa già riferimento il tuo oggetto, ovviamente.) Nella mia esperienza, le conversioni definite dall'utente di solito esistono tra tipi di valore anziché tipi di riferimento, quindi raramente si tratta di un problema.

Tutti questi contano come conversioni in termini di specifica, ma non contano come conversione di un oggetto in un oggetto di tipo diverso. Ho il sospetto che questo sia un caso in cui Jesse Liberty non ha una terminologia: l'ho notato nella Programmazione C # 3.0, che ho appena letto.

Comprende tutto?

Altri suggerimenti

Assolutamente no!

Convert prova a procurarti un Int32 tramite " qualsiasi mezzo possibile " ;. Il cast non fa nulla del genere. Con cast stai dicendo al compilatore di trattare l'oggetto come Int, senza conversione.

Dovresti sempre usare cast quando sai (in base alla progettazione) che l'oggetto è un Int32 o un'altra classe che ha un operatore di casting in Int32 (come float, per esempio).

Convert dovrebbe essere usato con String o con altre classi.

Prova questo

static void Main(string[] args)
{
    long l = long.MaxValue;

    Console.WriteLine(l);

    byte b = (byte) l;

    Console.WriteLine(b);

    b = Convert.ToByte(l);

    Console.WriteLine(b);

}

Risultato:

  

9223372036854775807

     

255

     

Eccezione non gestita:

     

System.OverflowException: il valore è   maggiore di Byte.MaxValue o inferiore   di Byte.MinValue a   System.Convert.ToByte (valore Int64)   [0x00000] su Test.Main   (System.String [] args) [0x00019] in   /home/marco/develop/test/Exceptions.cs:15

La migliore spiegazione che ho visto può essere vista sotto, seguita da un link alla fonte:

" ... La verità è un po 'più complessa di così. .NET fornisce tre metodi per passare dal punto A al punto B, per così dire.

Innanzitutto, c'è il cast implicito. Questo è il cast che non lo fa ti richiede di fare qualcosa di più di un compito:

int i = 5;
double d = i;

Questi sono anche chiamati " allargamento delle conversioni " e .NET te lo consente eseguili senza operatore del cast perché non potresti mai perderli informazioni che lo fanno: la possibile gamma di valori validi di un doppio comprende l'intervallo di valori validi per un int e quindi alcuni, quindi non farai mai questo compito e poi lo scoprirai orrore che il tempo di esecuzione sia sceso di alcune cifre rispetto al tuo valore int. Per tipi di riferimento, la regola dietro un cast implicito è che il cast non potrebbe mai generare un InvalidCastException: è chiaro al compilatore che il cast è sempre valido.

Puoi creare nuovi operatori di cast impliciti per i tuoi tipi (che significa che puoi eseguire cast impliciti che infrangono tutte le regole, se sei stupido a riguardo). La regola empirica di base è quella implicita il cast non può mai includere la possibilità di perdere informazioni nel file transizione.

Nota che la rappresentazione sottostante è cambiata in questo conversione: un doppio è rappresentato in modo completamente diverso da un int.

Il secondo tipo di conversione è un cast esplicito. Un cast esplicito è richiesto ovunque vi sia la possibilità di perdere informazioni, oppure c'è la possibilità che il cast potrebbe non essere valido e quindi lanciare una InvalidCastException:

double d = 1.5;
int i = (int)d;

Qui perderai ovviamente informazioni: sarò 1 dopo il cast, quindi lo 0,5 si perde. Questo è anche noto come & Quot; restringimento & Quot; conversione e il compilatore richiede l'inserimento di un cast esplicito (int) per indicare che sì, sai che le informazioni potrebbero andare perse, ma non ti interessa.

Allo stesso modo, con i tipi di riferimento il compilatore richiede cast espliciti in situazioni in cui il cast potrebbe non essere valido in fase di esecuzione, come segnale che sì, sai che c'è un rischio, ma sai cosa stai facendo.

Il terzo tipo di conversione è quello che comporta un cambiamento così radicale nella rappresentazione che i progettisti non hanno fornito nemmeno un esplicito cast: ti fanno chiamare un metodo per fare la conversione:

string s = "15";
int i = Convert.ToInt32(s);

Nota che non c'è nulla che richieda assolutamente una chiamata di metodo qui. I cast impliciti ed espliciti sono anche chiamate al metodo (è così che fai il tuo). I progettisti avrebbero potuto facilmente creare un esplicito operatore cast che ha convertito una stringa in un int. Il requisito che chiamare un metodo è una scelta stilistica piuttosto che fondamentale requisito della lingua.

Il ragionamento stilistico va in questo modo: String-to-int è a conversione complicata con molte opportunità per andare avanti orribilmente sbagliato:

string s = "The quick brown fox";
int i = Convert.ToInt32(s);

In quanto tale, la chiamata del metodo fornisce documentazione da leggere e in generale suggerisco che questo è qualcosa di più di un semplice cast.

Quando progetti i tuoi tipi (in particolare i tuoi tipi di valore), tu può decidere di creare operatori di cast e funzioni di conversione. Le linee divisione " cast implicito " ;, " esplicito cast " ;, e " funzione di conversione " il territorio è un po 'sfocato, quindi persone diverse possono rendere diverse decisioni su cosa dovrebbe essere cosa. Prova solo a ricordare perdita di informazioni e possibilità di eccezioni e dati non validi e ciò dovrebbe aiutarti a decidere. "

  • Bruce Wood, 16 novembre 2005

http://bytes.com/forum/post1068532-4.html

Il casting implica riferimenti

List<int> myList = new List<int>();
//up-cast
IEnumerable<int> myEnumerable = (IEnumerable<int>) myList;
//down-cast
List<int> myOtherList = (List<int>) myEnumerable;

Si noti che le operazioni su myList, come l'aggiunta di un elemento, si riflettono in myEnumerable e myOtherList. Questo perché sono tutti riferimenti (di vario tipo) alla stessa istanza.

L'up-casting è sicuro. Il down-casting può generare errori di runtime se il programmatore ha commesso un errore nel tipo. Il down-casting sicuro va oltre lo scopo di questa risposta.

La conversione comporta istanze

List<int> myList = new List<int>();
int[] myArray = myList.ToArray();

myList viene utilizzato per produrre myArray. Questa è una conversione non distruttiva (myList funziona perfettamente dopo questa operazione). Si noti inoltre che le operazioni su myList, come l'aggiunta di un elemento, non si riflettono in myArray. Questo perché sono istanze completamente separate.

decimal w = 1.1m;
int x = (int)w;

Ci sono operazioni che usano la sintassi del cast in C # che sono in realtà conversioni .

Semantica a parte, un rapido test mostra che sono NON equivalenti!
Fanno il compito in modo diverso (o forse svolgono compiti diversi).

x=-2.5 (int)x=-2 Convert.ToInt32(x)=-2
x=-1.5 (int)x=-1 Convert.ToInt32(x)=-2
x=-0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 1.5 (int)x= 1 Convert.ToInt32(x)= 2
x= 2.5 (int)x= 2 Convert.ToInt32(x)= 2

Nota i casi x=-1.5 e x=1.5.

Un cast sta dicendo al compilatore / interprete che l'oggetto è effettivamente di quel tipo (o ha un tipo di base / interfaccia di quel tipo). È una cosa abbastanza veloce da fare rispetto a un convertito in cui non è più il compilatore / interperter a fare il lavoro, ma una funzione che attua l'analisi di una stringa e la matematica per la conversione in un numero.

Casting significa sempre cambiare il tipo di dati di un oggetto. Questo può essere fatto ad esempio convertendo un valore float in un valore intero o reinterpretando i bit. Di solito è un'operazione supportata dalla lingua (leggi: supportata dal compilatore).

Il termine " convertendo " viene talvolta utilizzato per il cast, ma di solito viene eseguito da alcune librerie o dal proprio codice e non comporta necessariamente lo stesso cast. Ad esempio, se si dispone di un valore di peso imperiale e lo si converte in peso metrico, potrebbe rimanere lo stesso tipo di dati (ad esempio, float), ma diventare un numero diverso. Un altro esempio tipico è la conversione da gradi a radianti.

In un linguaggio / framework indipendente dal modo di parlare, la conversione da un tipo o classe è noto come casting.Questo è vero per .Rete, nonché, come i primi quattro linee show:

object x;
int y;

x = 4;

y = ( int )x;

C e C-come le lingue (ad esempio C#) utilizzare il (newtype)somevar la sintassi per la fusione.In VB.NET per esempio, ci sono esplicite funzioni built-in per questo.L'ultima riga dovrebbe essere scritto come:

y = CInt(x)

O, per i tipi più complessi:

y = CType(x, newtype)

Dove 'C', ovviamente, è l'abbreviazione di "cast".

.NETTO anche il Convert() funzione, tuttavia.Questo non è un built-in funzionalità di linguaggio (a differenza dei due precedenti), ma piuttosto in uno dei framework.Questo diventa più chiaro quando si utilizza una lingua che non è necessariamente utilizzato insieme con .NET:sono ancora molto probabilmente hanno i loro propri mezzi di casting, ma è .NET che aggiunge Convert().

Come Matt dice, la differenza di comportamento è che Convert() è più esplicito.Invece di limitarsi a raccontare il compilatore per il trattamento di y come un intero equivalente di x, si sono in particolare dicendogli di alter x in modo che è adatto per la classe integer, quindi assegnare il risultato a y.

Nel tuo caso particolare, il casting non quello che viene chiamato 'unboxing", mentre Convert() sarà effettivamente ottenere l'intero valore.Il risultato verrà visualizzato lo stesso, ma ci sono sottili differenze di meglio spiegato da Keith.

Secondo la tabella 1-7 intitolata " Metodi per la conversione esplicita " a pagina 55 nel Capitolo 1, Lezione 4 di Kit di allenamento autonomo MCTS (esame 70-536): Microsoft & # 174; .NET Framework 2.0 & # 8212; Application Development Foundation , c'è sicuramente una differenza tra di loro.

System.Convert è indipendente dalla lingua e converte " Tra i tipi che implementano l'interfaccia System.IConvertible . "

(tipo) operatore di cast è una funzione di linguaggio specifica per C # che converte " Tra tipi che definiscono operatori di conversione . quot &;

Inoltre, quando si implementano conversioni personalizzate, i consigli differiscono tra di loro.

Per la sezione intitolata Come implementare la conversione in tipi personalizzati a pagg. 56-57 nella lezione citata sopra, gli operatori di conversione (casting) sono pensati per semplificare le conversioni tra tipi numerici, mentre Convert () consente conversioni specifiche della cultura .

  

La tecnica scelta dipende dal tipo di conversione che si desidera eseguire:

     
      
  • Definisci operatori di conversione per semplificare il restringimento e l'ampliamento   conversioni tra tipi numerici.

  •   
  • Implementa System.IConvertible per abilitare la conversione   System.Convert. Utilizza questa tecnica per abilitare conversioni specifiche della cultura.

  •   
  • ...

  •   

Ora dovrebbe essere più chiaro che, poiché l'operatore di conversione del cast è implementato separatamente dall'interfaccia IConvertible, Convert () non è necessariamente solo un altro nome per il cast. (Ma posso immaginare dove una implementazione può riferirsi all'altra per garantire coerenza).

Non dimenticare gli altri metodi di cast e conversione delle variabili: as, Parse, TryParse nonché il cast implicito tra tipi di dati compatibili.

Questo sito ha un buon esempio di ciò che gli output per la maggior parte dei metodi: C # Boxing and Unboxing

Quindi date queste variabili di esempio:

int i = 3, x;
long l;
string s = "5";

Fondamentalmente puoi avere un cast implicito, tra due tipi compatibili:

l = i;

Cast esplicito usando unboxing o la come parola chiave:

s = (string)i;
//or
s = i as string;

Conversioni esplicite utilizzando metodi da System.Convert:

i = System.Convert.ToInt32(s);

Conversioni esplicite utilizzando metodi di un tipo di dati definito:

i = int.Parse(s);
i = int.TryParse(s, x);

Conversioni esplicite utilizzando metodi da un'istanza di una variabile:

s = i.ToString();

Penso che casting sia semplicemente un modo per fare assegnazioni tra due tipi compatibili.

Conversione è se devi copiare esplicitamente un valore da un tipo incompatibile a un altro e non puoi fidarti di male coercion .

Alcune buone informazioni anche su MSDN: Conversioni di casting e tipi

Il casting sta essenzialmente dicendo al runtime di " fingere " l'oggetto è il nuovo tipo. In realtà non converte o modifica l'oggetto in alcun modo.

Converti, tuttavia, eseguirà operazioni per trasformare un tipo in un altro.

Ad esempio:

char caster = '5';
Console.WriteLine((int)caster);

L'output di quelle istruzioni sarà 53, perché tutto il runtime ha fatto guardare il pattern di bit e trattarlo come un int. Ciò che si ottiene è il valore ASCII del carattere 5, anziché il numero 5.

Se si utilizza Convert.ToInt32 (caster), tuttavia, si otterrà 5 perché in realtà legge la stringa e la modifica correttamente. (Essenzialmente sa che il valore ASCII 53 è in realtà il valore intero 5.)

La differenza è se la conversione è implicita o esplicita. Il primo lassù è un cast, il secondo è una chiamata più esplicita a una funzione che converte. Probabilmente fanno la stessa cosa in modi diversi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top