EDIT: Ich habe jetzt blogged about this im Detail.
Meine ursprüngliche (und ich glaube, jetzt falsch) Gedanke: generic Einschränkungen nicht berücksichtigt bei der Überladungsauflösung und Typinferenz Phasen genommen - sie sind nur das Ergebnis der Überladungsauflösung zu validieren.
EDIT: Okay, nach einem Los davon zu gehen auf diesem, ich denke, ich bin da. Grundsätzlich war mein erster Gedanke fast korrekt.
Generische Typ-Constraints wirken nur, um Methoden aus einem Kandidatensatz in einem sehr begrenzten Satz von Umständen zu entfernen ... insbesondere, nur wenn der Typ eines Parameters selbst generisch ist; nicht nur ein Typparameter, sondern ein generischer Typ, der einen generischen Typparameter verwendet. An diesem Punkt werden die Einschränkungen für die Typparameter des generischen Typs überprüft, nicht die Einschränkungen für die Typparameter der generischen Methode, die Sie aufrufen.
Zum Beispiel:
// Constraint won't be considered when building the candidate set
void Foo<T>(T value) where T : struct
// The constraint *we express* won't be considered when building the candidate
// set, but then constraint on Nullable<T> will
void Foo<T>(Nullable<T> value) where T : struct
Also, wenn Sie versuchen, Foo<object>(null)
das obige Verfahren zu nennen nicht Teil des Kandidatensatzes, weil Nullable<object> value
die Zwänge des Nullable<T>
nicht erfüllt. Wenn es andere anwendbare Methoden gibt, könnte der Aufruf dennoch erfolgreich sein.
Jetzt im obigen Fall sind die Einschränkungen genau gleich ... aber sie müssen nicht sein. Betrachten wir zum Beispiel:
class Factory<TItem> where TItem : new()
void Foo<T>(Factory<T> factory) where T : struct
Wenn Sie versuchen, Foo<object>(null)
zu nennen, werden nach wie vor das Verfahren Teil des Kandidatensatzes sein - denn wenn TItem
object
, ausgedrückt die Einschränkung in Factory<TItem>
hält nach wie vor, und dass ist, was überprüft hat beim Aufbau des Kandidatensets. Wenn dies die beste Methode erweist, wird es dann nicht Validierung später, in der Nähe des Ende von 7.6.5.1:
Wenn die beste Methode, eine generische Methode ist, die Typargumente (geliefert oder abgeleitet) werden gegen die Einschränkungen (§4.4.4), die für die generische Methode deklariert sind, geprüft. Wenn ein Typargument die entsprechenden Integritätsbedingungen für den Typparameter nicht erfüllt, tritt ein Bindungszeitfehler auf.
Eric's blog post enthält weitere Details zu diesem Thema.
Ordentlich finden! Aber was ist deine Frage? Eine Problemumgehung? –
Gute Frage. Ich dachte, ich hätte eine einfache Antwort darauf, aber es stellte sich heraus, dass ich es nicht tat. Ich hoffe, es macht Ihnen nichts aus, dass meine "Antwort" eher eine Erkundung dessen ist, was vor sich geht, als eine Antwort an sich. –
Danke für Ihre Kommentare. Eamon - Entschuldigung, meine Frage ist nicht so klar - das ist der Grund, warum der Compiler nicht die beste Methode bestimmen kann. Nach dem Lesen der Kommentare und Fragen und des von LukeH bereitgestellten Links liegt das daran, dass der Compiler die Typenzwänge bei der Bestimmung der besten zu verwendenden Methode nicht berücksichtigt. –