web-dev-qa-db-fra.com

Appel de méthode à l'aide de l'opérateur ternaire

En jouant avec de nouveaux concepts, je suis tombé sur le Ternary Operator et c'est la beauté. Après avoir joué avec pendant un moment, j'ai décidé de tester ses limites.

Cependant, mon plaisir s'est terminé rapidement lorsque je n'ai pas pu obtenir une certaine ligne de code à compiler.

int a = 5;
int b = 10;
a == b ? doThis() : doThat() 

    private void doThis()
    {
        MessageBox.Show("Did this");
    }
    private void doThat()
    {
        MessageBox.Show("Did that");
    }

Cette ligne me donne deux erreurs:

Error   1   Only assignment, call, increment, decrement, and new object expressions can be used as a statement
Error   2   Type of conditional expression cannot be determined because there is no implicit conversion between 'void' and 'void'

Je n'ai jamais utilisé de Ternary Operator pour décider quelle méthode appeler, je ne sais pas non plus si c'est possible. J'aime juste l'idée d'une ligne unique If Else Statement pour l'appel de méthode.

J'ai fait un peu de recherche et je ne trouve aucun exemple de personne faisant cela, donc je pense que j'espère peut-être quelque chose qui ne peut pas fournir.

Si cela est possible, veuillez m'éclairer sur mes mauvaises actions, et ce n'est pas possible, y a-t-il une autre façon?

42
Kyle Uithoven

La raison pour laquelle la déclaration ci-dessus ne fonctionne pas a été fournie par les autres utilisateurs et n'a pas répondu à ma vraie question.

Après avoir joué un peu plus, j'ai compris que vous POUVEZ utiliser cet opérateur pour faire la déclaration ci-dessus, mais cela entraîne un mauvais code.

Si je devais changer la déclaration ci-dessus en;

int a = 5;
int b = 10;
int result = a == b ? doThis() : doThat(); 

private int doThis()
{
    MessageBox.Show("Did this");
    return 0;
}
private int doThat()
{
    MessageBox.Show("Did that");
    return 1;
}

Ce code compilera et exécutera comme il se doit. Toutefois, si ces méthodes n'étaient initialement pas destinées à renvoyer quoi que ce soit et faisaient référence à d'autres zones du code, vous devez désormais gérer un objet de retour à chaque fois pour appeler ces méthodes.

Sinon, vous pouvez maintenant utiliser un opérateur ternaire pour un sélecteur de méthode sur une ligne et même savoir quelle méthode il a appelée dans la ligne suivante en utilisant le résultat.

int result = a == b ? doThis() : doThat();

if (result == 0)
   MessageBox.Show("You called doThis()!");

Maintenant, ce code est absolument inutile et pourrait être facilement fait par un If Else, mais je voulais juste savoir si cela pouvait être fait, et ce que vous deviez faire pour le faire fonctionner.

Maintenant que je sais que vous pouvez renvoyer efficacement n'importe quel type dans ces méthodes, cela pourrait devenir un peu plus utile. Il peut être considéré comme une "mauvaise pratique de codage" mais peut devenir très utile dans des situations pour lesquelles il n'a jamais été SIGNIFIE.

Vous pourriez avoir accès à un objet ou à un autre en fonction de n'importe quelle condition et cela pourrait être très utile dans une ligne de code.

UserPrivileges result = user.Group == Group.Admin ? GiveAdminPrivileges() : GiveUserPrivileges();

private UserPrivileges GiveAdminPrivileges()
{
      //Enter code here
      return var;
}
private UserPrivileges GiveUserPrivileges()
{
      //Enter code here
      return var;
}

Bien sûr, cela peut être fait par une instruction If, mais je pense que l'utilisation de l'opérateur ternaire pour d'autres utilisations rend la programmation amusante. Maintenant, cela peut ne pas être aussi efficace qu'une instruction If Else, auquel cas, je ne l'utiliserais jamais.

3
Kyle Uithoven

l'opérateur ternaire est utilisé pour renvoyer des valeurs et ces valeurs doivent être affectées. En supposant que les méthodes doThis() et doThat() renvoient des valeurs, une simple affectation résoudra votre problème.

Si vous voulez faire ce que vous essayez, c'est possible, mais la solution n'est pas jolie.

int a = 5;
int b = 10;
(a == b ? (Action)doThis : doThat)();

Cela renvoie un délégué Action qui est ensuite invoqué par la parenthèse. Ce n'est pas un moyen typique d'y parvenir.

38
NerdFury

L'opérateur ternaire doit retourner quelque chose. Une utilisation typique est comme ceci:

int x = (a > b) ? a : b;

Si vous essayez quelque chose comme

a + b;

Le compilateur se plaindra.

(a > b) ? a - b : b - a;

est fondamentalement un raccourci pour "a - b" ou "b - a", qui ne sont pas des déclarations légitimes en soi.

18
iluxa

Si vous voulez vraiment invoquer les méthodes void dans un opérateur conditionnel, vous pouvez utiliser des délégués:

(something ? new Action(DoThis) : DoThat)();

Si les méthodes prennent des paramètres, cela deviendra plus compliqué.
Vous pouvez mettre des expressions lambda au conditionnel ou utiliser Action<T>.

Cependant, c'est une chose très stupide à faire.

9
SLaks

Vous devriez cependant pouvoir le faire:

        int a = 5;
        int b = 10;

        var func = a == b ? (Action)doThis : (Action)doThat; // decide which method

        func(); // call it

Mais ce n'est pas vraiment utile.

4
skarmats

L'opérateur conditionnel est une expression qui renvoie une valeur.
Vous ne pouvez pas l'utiliser avec des fonctions qui renvoient void.

À la place, vous devez utiliser un if normal.

2
SLaks

.NET ne prend pas (facilement) en charge (une version lisible) pour une raison. C'est très jankity et rend votre code difficile à lire. Les arbres logiques doivent être relativement faciles à parcourir. Si je devais entrer dans un travail et tout le code qu'ils avaient utilisé ternaire pour attribuer des valeurs, appeler des méthodes, etc. Je pense que je sortirais.

1
FreeAsInBeer