Opérateur conditionnel et délégué de comparaison

Étant donné deux implémentations des méthodes de comparaison:

// compares by Key... private static int CompareByKey(KeyValuePair x, KeyValuePair y) { return x.Key.CompareTo(y.Key); } // compares by Value... private static int CompareByValue(KeyValuePair x, KeyValuePair y) { return x.Value.CompareTo(y.Value); } 

Pourquoi le bloc de code d’opérateur conditionnel suivant ne serait-il pas compilé:

 Comparison<KeyValuePair> sortMethod; sortMethod = isSortByActualValue ? CompareByKey : CompareByValue; 

Erreur du compilateur: “Le type de l’expression conditionnelle ne peut pas être déterminé car il n’y a pas de conversion implicite entre ‘groupe de méthodes’ et ‘groupe de méthodes'”

Cependant, le bloc de code équivalent utilisant if-else n’a pas de problème:

 Comparison<KeyValuePair> sortMethod; if (isSortByActualValue) sortMethod = CompareByKey; else sortMethod = CompareByValue; 

(tout bon dans les deux missions ci-dessus)

Ainsi, l’opérateur conditionnel, si je lance le délégué Comparaison:

 Comparison<KeyValuePair> sortMethod; sortMethod = isSortByActualValue ? (Comparison<KeyValuePair>) CompareByKey : CompareByValue; 

(tout va bien dans la mission ci-dessus, quand le casting est fait même si le casting ne concerne que la vraie partie)

La méthode de l’erreur dit tout, mais elle n’est pas très intuitive. Si vous utilisez un nom de méthode sans l’invoquer, vous gérez un groupe de méthodes . “Groupe”, car une méthode peut être surchargée et le nom peut indiquer n’importe quelle méthode surchargée.

Maintenant, les groupes de méthodes sont convertibles implicitement en délégué avec une signature correspondante. C’est pourquoi votre affectation dans if fonctionne.

Jusqu’ici tout va bien. Cependant, l’opérateur conditionnel ?: Doit déduire un type commun en lequel ses deuxième et troisième arguments peuvent être convertis implicitement, et il ne considère pas toutes les conversions pour cela (cela poserait divers problèmes). Il s’agit simplement de déterminer si les deux arguments ont le même type ou si l’un est implicitement convertible en un autre.

Ce n’est pas le cas ici: bien que les deux arguments soient des groupes de méthodes, il s’agit en réalité de groupes de méthodes différents avec des types distincts et vous ne pouvez pas convertir un groupe de méthodes en un autre. Même si les deux peuvent facilement être convertis en délégué, le compilateur interdit cette utilisation.

La même chose est vraie pour les autres types, au fait:

 object = someBool ? "" : New List(); 

échoue également à comstackr, pour la même raison. Et encore une fois, nous pouvons faire cette compilation en convertissant explicitement l’un des arguments en un type de base commun:

 object = someBool ? (object) "" : New List(); 

Si vous avez une expression comme votre CompareByKey , elle n’a pas de type .Net spécifique, mais un type spécial «groupe de méthodes». En effet, vous pourriez avoir plusieurs méthodes appelées CompareByKey et il est difficile de savoir laquelle vous voulez (et cela fonctionne exactement de la même manière, même si vous n’avez qu’une seule méthode). En outre, vous ne savez pas quel type de délégué voulez-vous, par exemple Comparison> ou Func, int> .

Que pouvez-vous faire avec les groupes de méthodes? Vous pouvez les utiliser pour créer explicitement un délégué ( new Comparison>(CompareByKey) ). Ils sont également convertibles implicitement en delegates. C’est pourquoi votre version if fonctionne.

Alors, qu’est-ce que cela a à voir avec votre problème? Lorsque vous avez un opérateur conditionnel, le compilateur doit déterminer le type de l’expression entière et ne peut pas utiliser le type de la variable à laquelle vous l’atsortingbuez (ce n’est pas comment l’inférence de type fonctionne en C #). Et comme les deux expressions sont des groupes de méthodes et que les groupes de méthodes sont traités comme des types différents sans conversions implicites, le type de l’expression entière ne peut pas être déterminé. C’est pourquoi vous obtenez l’erreur.

Vous avez déjà trouvé un correctif: n’utilisez pas d’opérateur conditionnel ou spécifiez explicitement le type de l’un des opérandes à l’aide d’un transtypage (ou du constructeur délégué).