2016-03-25 30 views
7

mi sono imbattuto su questa cosa strana oggi:Perché questo non dovrebbe essere compilato?

http://www.yoda.arachsys.com/csharp/teasers.html

Domanda # 5.

Il codice:

using System; 

class Test 
{ 
    enum Foo 
    { 
     Bar, 
     Baz 
    }; 

    const int One = 1; 
    const int Une = 1; 

    static void Main() 
    { 
     Foo f = One - Une; 
     Console.WriteLine(f); 
    } 
} 

Ora, secondo le risposte su http://www.yoda.arachsys.com/csharp/teasers-answers.html per la domanda # 5

... E 'un bug conosciuto a causa di qualche ottimizzazione viene fatto troppo presto, la raccolta di costanti 0 e pensando che qualsiasi costante 0 conosciuta dovrebbe essere convertibile al valore 0 di qualsiasi enum. È con noi ora, e improbabile che venga mai riparato in quanto potrebbe rompere un codice tecnicamente illegale ma perfettamente funzionante. È possibile che le specifiche cambino invece, ovviamente.

Ma perché?

One & Une entrambi costanti. Cioè possono essere calcolati in fase di compilazione, quindi diventa Foo f = 0. E poiché 0 è un valore valido per qualsiasi enum, perché non dovrebbe essere compilato?

+0

Si sta cercando qualcosa come questo 'Foo f' e poi' f.Bar = One - Une; 'giusto? –

+0

Perché probabilmente il controllo "è un numero intero costante? Se sì, è 0? Allora è ok implicitamente lanciarlo in un enum" è fatto PRIMA dei calcoli costanti. – xanatos

+2

Tipo sicurezza. Anche se il tuo enum è supportato da un int, il tuo enum non è * un * int. Rappresenta i propri concetti e, in quanto tale, assegnare un int a un enum non è il modo corretto di lavorarci. –

risposta

7

Il problema non è che il compilatore può o non può far funzionare questo programma. Il problema è: cosa deve fare la specifica della lingua ?

Questo comportamento è una deviazione dalle specifiche, quindi è un errore del compilatore.

6.1.3 implicita La conversione di enumerazione una conversione enumerazione implicita permette decimale integer letterale 0 per essere convertiti in qualsiasi enum tipo e per qualsiasi tipo nullable-il cui tipo sottostante è un'enumerazione tipo.

Quindi deve essere un valore letterale. 1-1 non è uno zero letterale. 0 è zero letterale.

Mi chiedo perché la specifica dice "decimale". Ciò significa che hexadecimal-integer-literal non è incluso quindi 0x0 non dovrebbe funzionare neanche.

+0

perché compila bene a vs 2012 e 2015? –

+0

Il bug del compilatore non è stato risolto per motivi di compatibilità. Romperebbe il codice che in precedenza funzionava. – usr

+0

Ho appena saputo che c'era una versione del compilatore C# buggata che permetteva 'E e = new DateTime()'! Tuttavia, è stato risolto: https://blogs.msdn.microsoft.com/ericlippert/2006/03/29/the-root-of-all-evil-part-two/ – usr

Problemi correlati