2016-03-25 12 views
7

ich eher zufällig auf dieses seltsame Sache heute:Warum sollte das nicht kompilieren?

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

Frage # 5.

Der Code:

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); 
    } 
} 

Jetzt nach den Antworten auf http://www.yoda.arachsys.com/csharp/teasers-answers.html für Frage # 5

... Es ist ein bekannter Fehler aufgrund einiger Optimierung zu früh getan werden, sammeln Konstanten 0 und denke, dass jede bekannte Konstante 0 in den Wert 0 eines beliebigen Enums konvertiert werden kann. Es ist jetzt bei uns, und es ist unwahrscheinlich, dass es jemals repariert wird, da es einen Code kaputt machen könnte, der technisch illegal ist, aber einwandfrei funktioniert. Es ist möglich, dass sich die Spezifikation natürlich ändert.

Aber warum?

One & Une sind beide const. I.e. Sie können zur Kompilierzeit berechnet werden, so dass es Foo f = 0 wird. Und da 0 ist ein gültiger Wert für eine enum, warum sollte das nicht kompilieren?

+0

Sie suchen so etwas wie 'Foo f' und dann' f.Bar = One - Une; 'richtig? –

+0

Weil wahrscheinlich die Überprüfung "ist es eine konstante ganze Zahl? Wenn ja, ist es 0? Dann ist es in Ordnung, es implizit in eine Enum" zu werfen ist vor den konstanten Berechnungen getan. – xanatos

+2

Typ Sicherheit. Selbst wenn Ihre Enumeration durch ein int unterstützt wird, ist Ihr enum * nicht * ein int. Es stellt seine eigenen Konzepte dar, und daher ist es nicht die richtige Art, mit einem int zu einem enum zu arbeiten. –

Antwort

7

Das Problem ist nicht, dass der Compiler dieses Programm arbeiten kann oder kann. Das Problem ist: Was soll die Sprachspezifikation verlangen?

Dieses Verhalten ist eine Abweichung von der Spezifikation, so ist es ein Compiler-Fehler.

6.1.3 Implicit Enumeration Konvertierungen Eine implizite Enumeration Umwandlung erlaubt die dezimale ganzzahlige-Literal 0 irgendeinen enum-Typen umgewandelt werden, und zu jedem NULL festlegbaren-Typ, deren zugrunde liegenden Typ ist ein Aufzählungstyp.

Also muss es ein Literal sein. 1-1 ist keine literale Null. 0 ist literal Null.

Ich frage mich, warum die Spezifikation "Dezimal" sagt. Dies bedeutet, dass hexadecimal-integer-literal nicht enthalten ist, so dass 0x0 auch nicht funktionieren sollte.

+0

, warum es gut in vs 2012 und 2015 kompiliert? –

+0

Der Compiler-Fehler wurde aus Kompatibilitätsgründen nicht behoben. Es würde Code brechen, der vorher funktionierte. – usr

+0

Ich habe gerade erfahren, dass es eine fehlerhafte C# Compiler-Version gab, die 'E e = new DateTime()' erlaubte! Das wurde jedoch behoben: https://blogs.msdn.microsoft.com/ericlippert/2006/03/29/the-root-of-all-evil-part-two/ – usr

Verwandte Themen