Domanda

Sezione 6.1 conversioni implicite definisce un conversione identità nel seguente modo:

  

Un convertiti conversione identità da qualsiasi tipo allo stesso tipo. Questa conversione esiste tale che un'entità che già si è detto può essere un tipo richiesto per essere convertibile in quel tipo.

Ora, qual è lo scopo di frasi come queste?

  

(In §6.1.6 conversioni implicito riferimento)

     

Le conversioni implicite riferimento sono:

     
      
  • [...]
  •   
  • Da qualsiasi di riferimento di tipo per un di riferimento di tipo T se ha una conversione di identità o di riferimento implicito ad una di riferimento di tipo T 0 e T 0 ha una conversione identità T.
  •   

e

  

(conversioni in §6.1.7 Boxe)

     
      
  • Un tipo di valore ha una conversione di boxe per un tipo di interfaccia I se ha una conversione di boxe per un tipo di interfaccia I 0 e I 0 ha una conversione identità I .
  •   

Inizialmente sembrano ridondanti (tautologica). Ma devono essere lì per uno scopo, e allora perché non ci sono?

Può fare un esempio di due tipi T 1 , T 2 tale che T 1 farebbe non la conversione implicita T 2 se non fosse per i paragrafi sopra citati?

È stato utile?

Soluzione

Sezione 4.7 delle note specifiche che ci sia una conversione identità dalla Foo<dynamic> a Foo<object> e viceversa. La parte della specifica hai citato è scritto al fine di garantire che questo caso viene gestito. Cioè, se v'è una conversione riferimento implicito da T a C<object, object> poi c'è anche una conversione riferimento implicito a C<object, dynamic>, C<dynamic, object> e C<dynamic, dynamic>.

Si potrebbe ragionevolmente sottolineare che (1) l'intenzione di queste frasi è non ovvio - da qui la tua domanda - e confusione, e (2) che la sezione sulle conversioni di identità deve attraversare riferimento la sezione sulle conversioni dinamiche, e ( 3) frasi come questo nella marca specifica difficile per un implementor della specifica per chiaramente tradurre il linguaggio specifiche in un'implementazione. Come si fa a sapere se tale tipo esiste? La necessità specifiche non specifica algoritmi esatti, ma sarebbe bello se desse maggiori indicazioni.

La specifica è, purtroppo, non è un documento perfetto.

Altri suggerimenti

Aggiorna il 22-Set-2010:

I dubbi nessuno sta andando a leggere questo oltre Timwi. Anche così, ho voluto fare alcune modifiche a questa risposta alla luce del fatto che una nuova risposta ora è stato accettato e il dibattito continua ancora (almeno nel mio mondo forse immaginario) sul se i brani citati della spec sono tecnicamente ridondante. Io non sono l'aggiunta di molto, ma è troppo consistente per adattarsi in un commento. La maggior parte del aggiornamento può essere trovata all'intestazione "Conversione coinvolge il tipo dynamic" sotto.


Aggiorna il 19-Set-2010:

Nel vostro commento:

  

[T] la sua non ha senso.

Accidenti, Timwi, lei dice che molto . Ma va bene, allora; mi hai messo sulla difensiva, quindi ecco qui!

Disclaimer: io sono sicuramente non ha esaminato le specifiche più vicino si dispone. Sulla base di alcune delle vostre domande più recenti sembra che stavate cercando in esso un po 'ultimamente. Questo è naturalmente andando a rendere più familiarità con un sacco di dettagli che la maggior parte degli utenti su SO; quindi questa, come la maggior parte delle risposte è molto probabile che ricevere da chiunque non sia Eric Lippert, potrebbe non soddisfarvi.

Diversi locali

In primo luogo, la premessa della tua domanda è che se le dichiarazioni evidenziate sono ridondante , quindi non servono scopo . La premessa di La mia risposta è che le dichiarazioni ridondanti non sono necessariamente senza scopo se chiariscono qualcosa che non è evidente a tutti . Queste sono premesse contraddittorie. E se non possiamo essere d'accordo su premesse, non possiamo avere un argomento logico semplice. Stavo semplicemente chiedendo di ripensare la premessa.

La sua risposta, però, è stato quello di ribadire il tuo premessa: "Se le frasi sono davvero ridondanti, allora solo confondere il lettore e non chiariscono nulla"

(mi piace come si imposta te stesso come rappresentante per tutti i lettori del spec lì, tra l'altro.)

non posso dare la colpa per lo svolgimento di questa posizione, esattamente. Voglio dire, lo fa sembrano ovvia. E non ho dato esempi concreti nella mia risposta originale. Così di seguito cercherò di includere alcuni esempi concreti. Ma in primo luogo, mi permetta di prendere un passo indietro e offro il mio prendere sul perché questo strano conversione identità concetto esiste nelle specifiche, in primo luogo.

Lo scopo del conversione identità definizione

A prima vista, questa definizione sembra piuttosto superflua; Non è solo dicendo che un'istanza di qualsiasi tipo T è convertibile a ... beh, a T? Sì. Ma io ipotizzo * che lo scopo di questa definizione è quello di fornire le specifiche con il vocabolario corretto di utilizzare il concetto di tipo identità nel contesto di discutere conversioni .

Questo permette dichiarazioni sulle conversioni che sono essenzialmente transitivi in ??natura. Il primo punto citato dalla specifica come esempio di una dichiarazione tautologica rientra in questa categoria. Si dice che se una conversione implicita è definito per un certo tipo (lo chiamerò K) ad un altro tipo T 0 e T 0 ha una conversione identità T, allora K è implicitamente convertibile in T. Con la definizione di conversione identità di cui sopra, "ha una conversione identità per" davvero significa "è dello stesso tipo di". Quindi l'affermazione è ridondante .

Ma ancora una volta: il conversione identità esiste definizione in primo luogo di dotare le specifiche con un linguaggio formale per la descrizione di conversioni senza dover dire cose come "se T < sub> 0 e T sono davvero lo stesso tipo ".

OK, il tempo per esempi concreti.

Dove l'esistenza di una conversione implicita potrebbe non essere evidente a alcuni sviluppatori

Nota: A molto meglio esempio è stato fornito da Eric Lippert in la sua risposta alla domanda . Lascio questi primi due esempi come solo lievi rinforzi il mio punto. Ho anche aggiunto un terzo esempio che concretizza la conversione identità che esiste tra object e dynamic come sottolineato nella risposta di Eric.

transitivo conversione di riferimento

esempio di farvi avere due tipi, M e N, e hai una conversione implicita definita in questo modo:

public static implicit operator M(N n);

Codice Poi si può scrivere in questo modo:

N n = new N();
M m = n;

Ora diciamo che hai un file con questa affermazione using fino in alto:

using K = M;

E poi si deve, in seguito nel file:

N n = new N();
K k = n;

OK, prima di procedere, mi rendo conto che questo è ovvio per e me . , ma la mia risposta è, ed è stato da all'inizio, che potrebbe non essere evidente a tutti , e quindi specificando che - mentre ridondante - ha ancora un scopo .

che scopo è: per rendere chiaro a chiunque di graffiare la sua testa, guardando quel codice, è legale. Un conversione implicita esiste da N a M, e un conversione identità esiste da M a K (cioè, M e K sono dello stesso tipo); così una conversione implicita esiste da N a K. non è solo logico (sebbene possa essere logico); è proprio lì nelle specifiche . In caso contrario, si potrebbe erroneamente credere sarebbe necessario che qualcosa di simile al seguente:

K k = (M)n;

Chiaramente, non lo è.

transitivo boxe conversione

o prendere il tipo int. Un int può essere confezionato come un IComparable<int>, giusto? Quindi questo è legale:

int i = 10;
IComparable<int> x = i;

Ora considerare questo:

int i = 10;
IComparable<System.Int32> x = i;

Anche in questo caso, si , può essere ovvio a te, a me, e il 90% di tutti gli sviluppatori che potrebbe mai venire attraverso di esso. Ma per quella minoranza sottile che non si vede subito: un di conversione boxing esiste da int a IComparable<int>, e un conversione identità esiste da IComparable<int> a IComparable<System.Int32> (vale a dire, IComparable<int> e IComparable<System.Int32> sono dello stesso tipo); così esiste una conversione boxe da int a IComparable<System.Int32>.

La conversione coinvolge il tipo dynamic

ho intenzione di prendere in prestito dal mio esempio di conversione di riferimento di cui sopra e solo modificarlo leggermente per illustrare la relazione identità tra object e dynamic nella versione 4.0 delle specifiche.

Diciamo che abbiamo il M<T> tipi e N, e abbiamo definito da qualche parte il seguente conversione implicita:

public static implicit operator M<object>(N n);

Poi il seguente è legale:

N n = new N();
M<dynamic> m = n;

Chiaramente, quanto sopra è molto meno ovvie rispetto ai due esempi precedenti. Ma ecco la domanda da un milione di dollari:? sarebbe quanto sopra ancora essere legale anche se non esistessero i brani tratti dal spec citato nella domanda (vado a chiamata questi brani Q per brevità.) Se la risposta è sì, allora Q è infatti ridondante. Se no, allora non lo è.

Credo che la risposta è sì.

Si consideri la definizione di conversione identità , definito nella sezione 6.1.1 (Sono compresi l'intera sezione qui in quanto è abbastanza breve):

  

Un convertiti conversione identità da qualsiasi tipo allo stesso tipo. Questa conversione esiste tale che un'entità che già si è detto può essere un tipo richiesto per essere convertibile in quel tipo.

     

A causa equi object e dynamic sono considerativalente c'è una conversione identità tra object e dynamic, e tra tipi costruiti uguali quando si sostituisce tutte le occorrenze di dynamic con object . [sottolineatura mia]

(Questa ultima parte è anche incluso nel paragrafo 4.7, che definisce il tipo dynamic.)

Ora diamo un'occhiata al codice di nuovo. In particolare mi sono interessato a questa linea uno:

M<dynamic> m = n;

La legittimità di questa dichiarazione (trascurando Q - ricordate, la questione in discussione è l'ipotetico legittimità della dichiarazione di cui sopra se Q fatto non esiste), dal momento che M<T> e N sono tipi personalizzati, dipende dall'esistenza di una conversione implicita definito dall'utente tra N e M<dynamic>.

Non esiste una conversione implicita da N a M<object>. Con la sezione della specifica citato sopra, v'è una conversione identità tra M<object> e M<dynamic>. Con la definizione di conversione identità , M<object> e M<dynamic> sono dello stesso tipo .

Così, proprio come nei primi due (più evidenti) esempi, credo che sia vero che una conversione implicita esiste da N a M<dynamic> , anche senza prendere Q in considerazione , così come è vero che una conversione implicita esiste da N al K nel primo esempio e che una conversione boxe esiste da int al IComparable<System.Int32> nel secondo esempio.

Senza D , questo è molto meno evidente (quindi D 's esistenza); ma che non lo rende false (cioè, D non necessarie per questo comportamento da definire). Si rende solo meno evidente.

Conclusione

ho detto nella mia risposta originale che questa è la spiegazione "ovvio", perché mi sembrava che si stavano abbaiando contro l'albero sbagliato. inizialmente posto questa sfida:

  

Può fare un esempio di due tipi T 1 , T 2 tale che T 1 non sarebbe implicitamente convertibile in T 2 se non fosse per i paragrafi sopra citati?

Nessuno sta andando a rispondere a questa sfida, Timwi, perché è impossibile. Prendere la prima stralcio sulle conversioni di riferimento. Si dice che un tipo K è implicitamente convertibile in un tipo T se è implicitamente convertibile in T 0 e T 0 è lo stesso di T. Deconstruct questo, metterlo di nuovo insieme, e si è lasciato con una tautologia ovvia: K è implicitamente convertibile in T se è implicitamente convertibile in T. questo introducono nuove conversioni implicite? Certo che no.

Quindi forse il commento di Ben Voigt era corretta; Forse questi punti che si sta chiedendo sarebbe stato in una posizione migliore nelle note, piuttosto che nel corpo del testo. In ogni caso, è chiaro a me che sono ridondante, e quindi di iniziare con la premessa non possono essere ridondanti, altrimenti non sarebbero lì è di imbarcarsi su commissione di un pazzo. Essere disposti ad accettare che una dichiarazione ridondante può ancora far luce su un concetto che potrebbe non essere evidente a tutti, e sarà più facile da accettare queste affermazioni per quello che sono.

ridondante? Sì. Tautologico? Sì. Inutile? In il mio parere, no.

* Ovviamente, non ho avuto alcuna parte in forma scritta specifica linguaggio C #. Se l'ho fatto, questa risposta sarebbe molto più autorevole. Così com'è, rappresenta semplicemente un debole tentativo di ragazzo di dare un senso a un documento piuttosto complesso.


risposta originale

Credo che Non Sei (forse volutamente) che domina la risposta più ovvia.

Considerate queste due frasi nella vostra domanda:

  

(1) Inizialmente sembrano ridondanti   (Tautologica). (2) Ma devono esserci   per uno scopo, e allora perché non ci sono?

Per me, l'implicazione di queste due frasi insieme è che una dichiarazione tautologico non serve a nulla. Ma solo perché una dichiarazione segue logicamente da premesse stabilite, che non lo rende evidente a tutti. In altre parole, anche se (1) è vero, la risposta a (2) può essere semplicemente: per rendere il comportamento descritto chiaro a chiunque legga le specifiche .

Ora si potrebbe sostenere che, anche se qualcosa non è ovvio , lo fa ancora non appartiene a una specifica se si fornisce una definizione ridondante. Per questo potenziale obiezione, posso solo dire: essere realistici. Non è davvero pratico (a mio parere) a spulciare un documento escludendo tutte le dichiarazioni che sono semplicemente indicando i fatti che avrebbero potuto essere dedotte dalle dichiarazioni precedenti.

Se questo sono una pratica comune, penso che si può trovare un sacco di letteratura là fuori - non solo specifiche, ma documenti di ricerca, articoli, libri di testo, ecc - sarebbe un molto più breve, più densa e più difficile da capire.

Quindi: sì, forse sono ridondanti. Ma questo non nega il loro scopo.

  

Un convertiti conversione identità   qualsiasi tipo per lo stesso tipo . Questo   conversione esiste tale che un'entità   che ha già un tipo richiesto lattina   può dire di essere convertibile in che   tipo.

Questo dice che in C # -land, 1 == 1; uno Spade è uno Spade. Questa è la base di assegnare un riferimento all'oggetto a una variabile dello stesso tipo; se una variabile digitato T1 e T2 sono uno digitato in realtà due forcelle, è possibile assegnare uno all'altro senza dover esplicitamente lanciare uno come Spade. Immaginate un C # variante in cui le assegnazioni dovevano assomigliare a questo:

Spade mySpade = new Spade();
Spade mySpade2;

mySpade2 = (Spade)mySpade; //explicit cast required

Inoltre, una "identità" in matematica indica che un'espressione che restituisce un risultato fornita una serie di ingressi è equivalente a un'altra espressione che produce lo stesso risultato dato gli stessi ingressi. Nella programmazione, ciò significa che un'espressione o una funzione che restituisce un'istanza di un tipo è equivalente a quel tipo, senza conversione esplicita. Se questo non era in possesso, sarebbe necessario il seguente codice:

public int myMethod() { /*Do something*/ }
...
int myInt = (int)myMethod(); //required even though myMethod() evals to an int.
...
int myInt = (int)(1 + 2); //required even though 1, 2, and 1+2 eval to an int.

La seconda regola pratica dice che un tipo di valore può essere assegnato ad una variabile membro su una classe se, in parte, la variabile membro (un tipo scatolato per definizione, come contenitore è un tipo di riferimento) viene dichiarato il stesso tipo. Se questa regola non sono stati specificati, in teoria, una versione di C # potrebbe esistere in cui i tipi di valore puri dovrebbero essere esplicitamente convertito alla loro analogico di riferimento, al fine di essere memorizzato come variabile membro su una classe. Immaginate, per esempio, una versione di C #, in cui i tipi di blu Parola (int, float, decimali) ei nomi delle classi azzurro (Int32, Float, decimale) di cui due molto diverse, i tipi solo-esplicitamente convertibili, e int , galleggiante, ecc decimale non erano legali, come tipi di variabili membro perché non erano tipi di riferimento:

public class MyClass
{
  Int32 MyBoxedValueType; //using "int" not legal
}

...

MyClass myClass = new MyClass();
int theInt = 2;

myClass.MyBoxedValueType = (Int32)theInt; //explicit cast required

So che può sembrare stupido, ma a un certo livello, queste cose devono essere conosciuti, e nei computer, è necessario specificare ogni cosa. Leggere il libro delle regole USA Hockey per l'hockey su ghiaccio qualche tempo; la prima regola nel libro è che il gioco deve essere giocato su una superficie ghiacciata. E 'uno degli ultimi "e duhs", ma anche una verità fondamentale del gioco che deve essere intesa in modo che qualsiasi altra regola di dare un senso.

Maggio è tale che il codice garanzie pass-through quando viene chiamato come Convert.ChangeType(client, typeof(Client)), indipendentemente se IConvertible è implementato.

Guardate nella fonte di ChangeType da mscorlib con riflettore e notare le condizioni in cui value viene restituito così com'è.

Ricordati di un operatore di = non è una conversione, solo un insieme di riferimento. Quindi il codice come Client client_2 = client_1 non esegue alcun conversioni implicite. Se una conversione implicita identità è dichiarata poi all'errore CS0555 viene emesso.

Credo che le specifiche dice di lasciar il compilatore C # gestire tali casi, e quindi punto non cercare manualmente per definire conversioni di identità.

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