true
Wie ist null + true
eine Zeichenfolge, da es sich nicht um einen Zeichenfolgentyp handelt ?
string s = true; //Cannot implicitly convert type 'bool' to 'string'
bool b = null + true; //Cannot implicitly convert type 'string' to 'bool'
Was ist der Grund dafür?
Antworten:
So bizarr dies auch erscheinen mag, es folgt einfach den Regeln aus der C # -Sprachenspezifikation.
Aus Abschnitt 7.3.4:
Lassen Sie uns dies der Reihe nach durchgehen.
X ist hier der Nulltyp - oder überhaupt kein Typ, wenn Sie es so sehen möchten. Es werden keine Kandidaten bereitgestellt. Y ist
bool
, was keine benutzerdefinierten bereitstellt+
Operatoren . Der erste Schritt findet also keine benutzerdefinierten Operatoren.Der Compiler fährt dann mit dem zweiten Aufzählungspunkt fort und betrachtet die vordefinierten Implementierungen des binären Operators + und ihre aufgehobenen Formen. Diese sind in Abschnitt 7.8.4 der Spezifikation aufgeführt.
Wenn Sie sich diese vordefinierten Operatoren ansehen, ist nur einer anwendbar
string operator +(string x, object y)
. Der Kandidatensatz hat also einen einzigen Eintrag. Das macht den letzten Aufzählungspunkt sehr einfach ... Überlastungsauflösung wählt diesen Operator aus und gibt einen Gesamtausdruckstyp von anstring
.Ein interessanter Punkt ist, dass dies auch dann auftritt, wenn für nicht erwähnte Typen andere benutzerdefinierte Operatoren verfügbar sind. Beispielsweise:
Das ist in Ordnung, wird aber nicht für ein Null-Literal verwendet, da der Compiler nicht weiß, wie er nachsehen soll
Foo
. Es muss nur berücksichtigt werden,string
da es sich um einen vordefinierten Operator handelt, der explizit in der Spezifikation aufgeführt ist. (Tatsächlich ist es kein Operator, der durch den Zeichenfolgentyp definiert ist ... 1 ) Das bedeutet, dass dies nicht kompiliert werden kann:Andere Typen von zweiten Operanden verwenden natürlich einige andere Operatoren:
1 Sie fragen sich möglicherweise, warum es keinen String + -Operator gibt. Es ist eine vernünftige Frage, und ich bin nur raten , auf die Antwort, aber bedenken Sie diesen Ausdruck:
Wenn
string
der C # -Compiler kein spezielles Gehäuse hätte, wäre dies genauso effektiv:Das hat also zwei unnötige Zwischenzeichenfolgen erzeugt. Da es jedoch innerhalb der Compiler spezielle Unterstützung, es ist tatsächlich die Lage , die wie oben zu kompilieren:
Dadurch kann nur eine einzelne Zeichenfolge mit genau der richtigen Länge erstellt werden, wobei alle Daten genau einmal kopiert werden. Nett.
quelle
true
nicht konvertierbar iststring
. Wenn der Ausdruck gültig wärestring
, wäre der Typ , aber in diesem Fall macht der Fehler beim Konvertieren in einen String den gesamten Ausdruck zu einem Fehler und hat daher keinen Typ.x
ist vom Typstring
. Beachten Sie, dass die hier verwendete Signatur lautetstring operator+(string, object)
- sie wirdbool
inobject
(was in Ordnung ist) konvertiert , nicht instring
.Der Grund dafür ist, dass nach der Einführung der
+
dann die Bindungsregeln für den C # -Operator ins Spiel kommen. Dabei werden die+
verfügbaren Operatoren berücksichtigt und die beste Überlastung ausgewählt. Einer dieser Operatoren ist der folgendeDiese Überladung ist mit den Argumenttypen im Ausdruck kompatibel
null + true
. Daher wird es als Operator ausgewählt und als wesentlich((string)null) + true
bewertet, was den Wert ergibt"True"
.Abschnitt 7.7.4 der C # -Sprachenspezifikation enthält die Details zu dieser Auflösung.
quelle
operator+
für gibtstring
. Stattdessen existiert es nur im Kopf des Compilers und übersetzt es einfach in Aufrufe fürstring.Concat
Der Compiler macht sich auf die Suche nach einem Operator + (), der zuerst ein Nullargument annehmen kann. Keiner der Standardwerttypen ist qualifiziert, null ist für sie kein gültiger Wert. Die einzige Übereinstimmung ist System.String.operator + (), es gibt keine Mehrdeutigkeit.
Das zweite Argument dieses Operators ist ebenfalls eine Zeichenfolge. Das geht kapooey, kann Bool nicht implizit in String konvertieren.
quelle
Interessanterweise wird mit Reflector der folgende Code überprüft:
wird vom Compiler in dieses umgewandelt:
Die Argumentation hinter dieser "Optimierung" ist etwas seltsam, muss ich sagen, und reimt sich nicht auf die Operatorauswahl, die ich erwarten würde.
Auch der folgende Code:
verwandelt sich in
wo
string b = true;
wird eigentlich vom Compiler nicht akzeptiert.quelle
null
wird in eine Nullzeichenfolge umgewandelt, und es gibt einen impliziten Konverter von bool in eine Zeichenfolge, sodass dietrue
in eine Zeichenfolge umgewandelt wird und dann+
Operator angewendet: Es ist wie folgt: Zeichenfolge str = "" + true.ToString ();wenn Sie es mit Ildasm überprüfen:
string str = null + true;
es ist wie folgt:
quelle
Verrückt?? Nein, es muss einen Grund dafür geben.
Jemand ruft an
Eric Lippert
...quelle
Der Grund dafür ist die Bequemlichkeit (das Verketten von Zeichenfolgen ist eine häufige Aufgabe).
Wie BoltClock sagte, ist der Operator '+' für numerische Typen und Zeichenfolgen definiert und kann auch für unsere eigenen Typen definiert werden (Operatorüberladung).
Wenn die Typen des Arguments keinen überladenen Operator '+' enthalten und es sich nicht um numerische Typen handelt, verwendet der Compiler standardmäßig die Verkettung von Zeichenfolgen.
Der Compiler fügt einen Aufruf ein,
String.Concat(...)
wenn Sie mit '+' verketten, und die Implementierung von Concat ruft ToString für jedes übergebene Objekt auf.quelle