J'ai une classe Animal
et sa sous-classe Dog
. Je me retrouve souvent à coder les lignes suivantes:
if (animal is Dog)
{
Dog dog = animal as Dog;
dog.Name;
...
}
Pour la variable Animal animal;
.
Y a-t-il une syntaxe qui me permet d'écrire quelque chose comme:
if (Dog dog = animal as Dog)
{
dog.Name;
...
}
c#
casting
if-statement
Michael
la source
la source
bool
condition?null
=false
En C #; C # n'autorise que les booléens réels ou les objets implicitement convertibles en booléens dans desif
conditions. Ni les valeurs nulles ni aucun des types entiers ne sont implicitement convertibles en booléens.Réponses:
La réponse ci-dessous a été écrite il y a des années et mise à jour au fil du temps. À partir de C # 7, vous pouvez utiliser la correspondance de modèles:
Notez que cela
dog
est toujours dans la portée après l'if
instruction, mais n'est pas définitivement attribué.Non, il n'y en a pas. Il est cependant plus idiomatique d'écrire ceci:
Etant donné que "comme suivi de si" est presque toujours utilisé de cette façon, il pourrait être plus logique qu'il y ait un opérateur qui exécute les deux parties en une seule fois. Ce n'est pas actuellement en C # 6, mais peut faire partie de C # 7, si la proposition de correspondance de modèle est implémentée.
Le problème est que vous ne pouvez pas déclarer une variable dans la partie condition d'une
if
instruction 1 . L'approche la plus proche à laquelle je puisse penser est la suivante:C'est juste méchant ... (Je viens de l'essayer, et ça marche. Mais s'il vous plaît, ne faites pas ça. Oh, et vous pouvez déclarer
dog
utiliservar
bien sûr.)Bien sûr, vous pouvez écrire une méthode d'extension:
Alors appelez-le avec:
Vous pouvez également combiner les deux:
Vous pouvez également utiliser une méthode d'extension sans expression lambda d'une manière plus propre que la boucle for:
Ensuite:
1 Vous pouvez attribuer des valeurs dans les
if
instructions, bien que je le fasse rarement. Ce n'est pas la même chose que de déclarer des variables. Il n'est pas terriblement inhabituel pour moi de le faire dans unwhile
moment lors de la lecture de flux de données. Par exemple:Ces jours-ci, je préfère normalement utiliser un wrapper qui me permet d'utiliser,
foreach (string line in ...)
mais je considère ce qui précède comme un modèle assez idiomatique. Il n'est généralement pas agréable d'avoir des effets secondaires dans une condition, mais les alternatives impliquent généralement la duplication de code, et lorsque vous connaissez ce modèle, il est facile de bien faire.la source
EVIL EVIL EVIL
, mais je ne suis pas sûr.AsEither(...)
, je pense que c'est un peu plus clair queAsIf(...)
, donc je peux écriremyAnimal.AsEither(dog => dog.Woof(), cat => cat.Meeow(), unicorn => unicorn.ShitRainbows())
.En cas d'
as
échec, il revientnull
.la source
if
instruction et non dans la portée externe.if
peut avoir un résultat booléen et une affectation.Dog dog; if ((dog = animal as Dog) != null) { // Use Dog }
mais cela introduit toujours la variable dans la portée externe.Vous pouvez affecter la valeur à la variable, tant que la variable existe déjà. Vous pouvez également définir l'étendue de la variable pour permettre à ce nom de variable d'être réutilisé ultérieurement dans la même méthode, si cela pose un problème.
en supposant
obtient la sortie:
Le modèle d'affectation de variable dans le test est également utilisé lors de la lecture de blocs d'octets à partir de flux, par exemple:
Le modèle de portée variable utilisé ci-dessus, cependant, n'est pas un modèle de code particulièrement courant et si je le voyais utilisé partout, je chercherais un moyen de le refactoriser.
la source
Il y en aura probablement dans C # 6.0. Cette fonctionnalité est appelée "expressions de déclaration". Voir
https://roslyn.codeplex.com/discussions/565640
pour plus de détails.
La syntaxe proposée est:
Plus généralement, la fonctionnalité proposée est qu'une déclaration de variable locale peut être utilisée comme expression . Cette
if
syntaxe n'est qu'une belle conséquence de la fonctionnalité plus générale.la source
Try*
(par exemple,TryParse
). Cette fonctionnalité fait non seulement de tels appels dans une seule expression (comme ils devraient l'être, IMO), mais permet également une portée plus claire de ces variables. Je suis enthousiaste à l'idée que leout
paramètre d'uneTry
méthode soit étendu à son conditionnel; cela rend plus difficile l'introduction de certains types de bogues.L'une des méthodes d'extension que j'écris et que j'utilise souvent * est
Qui pourrait être utilisé dans cette situation comme
Et puis
name
est le nom du chien (s'il s'agit d'un chien), sinon nul.* Je n'ai aucune idée si c'est performant. Cela n'a jamais été un goulot d'étranglement dans le profilage.
la source
Aller à contre-courant ici, mais peut-être que vous le faites mal au départ. Vérifier le type d'un objet est presque toujours une odeur de code. Tous les animaux, dans votre exemple, n'ont-ils pas un nom? Ensuite, appelez simplement Animal.name, sans vérifier s'il s'agit d'un chien ou non.
Vous pouvez également inverser la méthode pour appeler une méthode sur Animal qui fait quelque chose différemment selon le type concret de l'Animal. Voir aussi: Polymorphisme.
la source
Déclaration plus courte
la source
Voici un code sale supplémentaire (pas aussi sale que celui de Jon, cependant :-)) dépendant de la modification de la classe de base. Je pense que cela capture l'intention tout en ratant peut-être le point:
la source
Si vous devez faire plusieurs comme-si un après un (et utiliser le polymorphisme n'est pas une option), envisagez d'utiliser une construction SwitchOnType .
la source
Le problème (avec la syntaxe) n'est pas lié à l'affectation, car l'opérateur d'affectation en C # est une expression valide. C'est plutôt avec la déclaration souhaitée, car les déclarations sont des déclarations.
Si je dois écrire du code comme ça, j'écrirai parfois (selon le contexte plus large) le code comme ceci:
La syntaxe ci-dessus présente des avantages (qui est proche de la syntaxe demandée) car:
dog
dehors duif
entraînera une erreur de compilation car il n'est pas attribué une valeur ailleurs. (C'est, ne pas affecterdog
ailleurs.)if/else if/...
(Il y en a seulement autantas
que nécessaire pour sélectionner une branche appropriée; c'est le grand cas où je l'écris sous cette forme quand je le dois.)is/as
. (Mais aussi fait avec laDog dog = ...
forme.)Pour vraiment isoler
dog
du reste du monde, un nouveau bloc peut être utilisé:Bon codage.
la source
tu peux utiliser quelque chose comme ça
// Déclare la variable bool temp = false;
la source
Une autre solution EVIL avec des méthodes d'extension :)
Personnellement, je préfère la manière propre:
la source
Une instruction if ne le permettra pas, mais une boucle for le fera.
par exemple
Dans le cas où la façon dont cela fonctionne n'est pas immédiatement évidente, voici une explication étape par étape du processus:
itération.
la source
la source
IDK si cela aide quelqu'un mais vous pouvez toujours essayer d'utiliser un TryParse pour affecter votre variable. Voici un exemple:
La variable totale serait déclarée avant votre instruction if.
la source
Je viens d'inclure l'instruction if pour créer une ligne de code qui ressemble à ce qui vous intéresse. Cela aide simplement à compresser le code une partie et je l'ai trouvé plus lisible, en particulier lors de l'imbrication des affectations:
la source
Je sais que je suis super duper en retard à la fête, mais j'ai pensé que je publierais ma propre solution de contournement à ce dilemme puisque je ne l'ai pas encore vue ici (ou ailleurs d'ailleurs).
Avec cela, vous pouvez faire des choses telles que:
REMARQUE IMPORTANTE: Si vous souhaitez utiliser TryAs () en utilisant une interface, vous DEVEZ avoir cette interface héritant de IAble.
Prendre plaisir! 🙂
la source