Der Compiler ruft keine geeignete generische Überladung auf, wenn er mit dem Werttyp übergeben wurde

8

Ich habe öffentliche Funktionen wie folgt:

%Vor%

Grundsätzlich möchte ich Referenztypen und NULL-Typen individuell behandeln. Es kompiliert; bis ich nach Werttypen rufe. Für Referenztypen wird kompiliert.

%Vor%

Was ist das für eine echte Mehrdeutigkeit? Wenn T int ist, kann es die struct-überladung nicht korrekt aufrufen? Auch:

%Vor%

Warum erkennt der Compiler nur die Überladung des Referenztyps? Ich habe versucht, zwei Überladungen zu haben:

%Vor%

Das Problem ist weiterhin aufgetreten. Und natürlich, die ersten beiden Methoden kompilieren hier nicht, da das Überladen nicht nur auf der Basis von Beschränkungen funktioniert.

Ich habe versucht, die class bedingte Überladung zu entfernen und nur die struct -beschränkte Überladung beizubehalten, so:

%Vor%

Bleibt mir nur noch die Umbenennung der beiden Funktionen? Ich halte es für angebracht, einen einheitlichen Namen zu haben, damit sich der Anrufer nicht um die Details der Implementierung kümmern muss, sondern einfach Get aufrufen muss jeder Typ.

Update: Marc's Lösung funktioniert nicht, wenn ich den optionalen Parameter vermeiden muss.

%Vor%

Aber es gibt noch mehr Magie: (: (

%Vor%

Ich erwarte auf jeden Fall, dass derselbe Compiler-Fehler mich verärgert. Aber nein, es funktioniert diesmal.

%Vor%

Wenn also die Überladungsauflösung vor der Einschränkungsprüfung steht, wie Marc sagt, sollte ich nicht auch diesmal denselben Fehler bekommen? Aber nein. Warum ist es so? Was zur Hölle geht hier vor? : x

    
nawfal 07.02.2013, 11:18
quelle

3 Antworten

5

Überprüfung der Abhängigkeit erfolgt nach Überladungsauflösung, IIRC; Die Überladungsauflösung scheint die erste Version vorzuziehen. Sie können jedoch die Verwendung des anderen erzwingen:

%Vor%

oder sogar:

%Vor%

Persönlich würde ich wahrscheinlich nur den Namen ändern, um die Mehrdeutigkeit zu vermeiden.

    
Marc Gravell 07.02.2013, 11:23
quelle
1

Interessanterweise wird der Compiler die Integritätsbedingungen überprüfen, die in generischen Typen angegeben sind, die innerhalb einer Methodensignatur verwendet werden, aber nicht für Einschränkungen innerhalb der Signatur selbst.

Wenn also eine Methode zwei Parameter akzeptierte, einen vom Typ T where T : struct zusammen mit einem Nullable<T>[] , würde der Compiler die Methode für keine T , die keine Struktur war, nicht berücksichtigen. Die angegebene struct -Einschränkung der Methode für T wird bei der Auswertung von Überladungen nicht berücksichtigt, aber die Tatsache, dass Nullable<T> T auf struct beschränkt, ist.

Ich finde wirklich die völlige Unfähigkeit, Einschränkungen in der Überlastungsevaluation bizarr zu betrachten, da man einen Standard-Nullwert für den Parameter Nullable<T>[] angeben und so tun könnte, als wäre der Parameter nicht vorhanden. Die vb.net-Compiler und C # -Compiler scheinen sich jedoch zu unterscheiden, wenn es darum geht, was sie als mehrdeutig ansehen und was sie akzeptieren.

    
supercat 10.02.2013 23:31
quelle
0

Lass mich versuchen, mich selbst zu beantworten.

Wie Marc sagt, wird die Bedingungsprüfung nach der Überladungsauflösung und zwischen

durchgeführt %Vor%

und

%Vor%

Überladungsauflösung bevorzugt die class Version. Aber das ist nur dann der Fall, wenn der Compiler die Wahl zwischen zwei ähnlichen Überladungen hat ( ohne den optionalen Parameter, wobei beide Überladungen gleich werden, wobei die Einschränkung vernachlässigt wird ). Wenn die Einschränkung angewendet wird, schlägt der Aufruf für Get<int> fehl, da int nicht class ist.

Die Dinge ändern sich etwas, wenn Standardparameter bereitgestellt werden. Wenn ich anrufe

%Vor%

Der Compiler ist in der Lage, die richtige Überladung aufzurufen, aber welche Überladung akzeptiert nun int oder T where T: struct ? Es gibt keinen. Im angegebenen Beispiel wird erwartet, dass der zweite Parameter T? und nicht T ist. Der Compiler löst das Überladen nicht automatisch durch Anwenden aller verfügbaren Umwandlungen für jeden Argumenttyp. Es ist kein Fehler, aber das ist ein Feature weniger, das ist alles . Wenn ich das tue:

%Vor%

es funktioniert, die richtige Überladung wird aufgerufen. Dies ist auch im zweiten Beispiel der Fall. Es funktioniert, weil ich den richtigen Parameter zur Verfügung stelle.

Wenn ich anrufe:

%Vor%

obj ist bekanntermaßen g und daher T gleich Guid . Aber wenn ich anrufe

%Vor%

Das funktioniert nicht, da g jetzt Guid und nicht Guid? ist und der Compiler das Casting nicht automatisch durchführt, sondern dem Compiler explizit mitteilen muss.

Ich bin in Ordnung mit der Tatsache, dass der Compiler das Casting nicht automatisch durchführt, da dies für jeden möglichen Typ zu viel zu berechnen ist, aber was ein Mangel in C # zu sein scheint, ist die Tatsache, dass constraint Die Überprüfung ist nicht an der Überladungsauflösung beteiligt. Das heißt, selbst wenn ich den Typ wie mango.Get<int>() oder mango.Get<int>(0) zur Verfügung stelle, wird die Überladungsauflösung die struct Version nicht bevorzugen und default(int?) für das Argument defaultValue verwenden. . Sieht für mich seltsam aus.

    
nawfal 10.02.2013 12:36
quelle