6
votes

Pourquoi des types de référence qui moulaient jamais lorsque vous pouvez utiliser "comme"?

Dupliqué possible:
Casting: (nouveautype) vs objet comme nouveautype

en C #, pourquoi déjà des types de référence lorsque vous pouvez utiliser "comme"?

casting peut générer des exceptions alors que "comme" va évitaira vers null si la coulée échoue.

ne serait pas plus facile à utiliser avec référence types dans tous les cas?

par exemple: xxx

plutôt que xxx


1 commentaires

@Jarrett Meyer - Cette question demande quelle est la différence. Cette question est différente. Connaissant la différence, il demande pourquoi une fonte qui jette est meilleure qu'un casting qui ne jette pas.


8 Réponses :


2
votes

opérateur 'comme "fonctionne avec des types de référence uniquement.


1 commentaires

La question a été mise à jour pour clarifier qu'il s'agit uniquement de types de référence uniquement (comme il parle de null Je pensais déjà clair déjà).



2
votes

Parfois, vous voulez que l'exception soit lancée. Parfois, vous voulez essayer de convertir et NULLS est correct. Comme déjà indiqué, comme ne fonctionnera pas avec des types de valeur.


3 commentaires

Damn, y'battez-moi à cela;) Exactement, parfois, vous voulez qu'une exception soit lancée, ce qui est parfaitement valide. +1


Pourquoi voudriez-vous que l'exception soit lancée?


Parce que le code d'appel a fait quelque chose qui n'a pas de sens et que la seule réponse sensible est de lancer une exception. Ce n'est pas différent de la façon dont si vous appeliez Charge () sur un xmldocument avec du contenu qui n'était pas XML, vous voulez que cela jette une exception. Ne pas le faire, il vous laisse simplement un objet qui ne peut pas être utilisé sensiblement, mais que vous ne savez pas ne peut pas être utilisé sensiblement.



0
votes

de msdn ( comme (référence C #) ): < / p>

L'opérateur n'effectue que des conversions de référence et des conversions de boxe. L'opérateur que l'opérateur ne peut pas effectuer d'autres conversions, telles que des conversions définies par l'utilisateur, qui doivent être effectuées à la place à l'aide d'expressions moulées.


0 commentaires

0
votes

Prendre en compte tous les commentaires, nous avons rencontré cela simplement l'autre jour et que vous vous demandiez pourquoi vous feriez une distribution directe en utilisant le mot-clé comme . Et si vous veux la distribution à échouer? C'est parfois l'effet souhaitable que vous souhaitez d'un casting si vous coulez d'un objet NULL. Vous appuyez ensuite sur la pile d'appel.

Donc, si vous voulez que quelque chose échoue, utilisez une distribution directe, si vous acceptez cela ne pas échouer, utilisez le mot clé comme


2 commentaires

Pourquoi voudriez-vous que la volonté échoue? En outre, si la distribution échoue à l'aide de "comme", vous recevrez NULL.


Certains environnements logiciels répondent à des types génériques, comme la nôtre le fait, afin d'accroître la flexibilité. Les nouveaux types peuvent être introduits ad-hoc. Par exemple, nous utilisons des roulettes dynamiques pouvant convertir d'un type à un autre, même si elles ne sont pas liées. Ceci est fait pour que le type de fin est "convivial" (peut-être immuable ou avec des champs cachés). Si la distribution ne fonctionne pas, nous devons savoir à ce sujet!



1
votes

Si, lorsque vous écrivez le code pour effectuer la distribution, vous êtes sûr que la distribution doit fonctionner, vous devez utiliser (dataGridView) myObject . De cette façon, si la distribution échoue à l'avenir, votre hypothèse sur le type de MyObject provoquera une exception de moulage non valide au point où vous effectuez la distribution, au lieu d'une exception de référence NULL à un moment donné.

Si vous souhaitez gérer le cas où MyObject n'est pas un DataGridView, utilisez ensuite comme et vérifiez probablement qu'il est null avant de faire quelque chose avec elle.

tl; dr si votre code suppose quelque chose et que l'hypothèse est erronée au moment de l'exécution, le code devrait lancer une exception.


0 commentaires

9
votes

Considérez les alternatives suivantes:

SomeClass c = (someObj as SomeClass) ?? _stockImpl;


15 commentaires

+1 Je continue à voir foo (SomeoBJ en tant que soméclasse); dans le code (sans un NULL chèque, c'est-à-dire). Cela me déflère pourquoi les gens font cela. Y a-t-il un livre quelque part qui dit (soméclass) sont mauvais?


N'est-il pas plus facile de vérifier si la variable est NULL après la déclaration "comme", plutôt que de faire face à une exception?


Pouvez-vous faire quelque chose d'utile lorsque TOOROBJ est null ? Sinon, si votre code peut supposer que personnobj est en fait soméclass - alors quel est le point?


Mais si vous n'avez pas écrit foo , et j'ai fait? Comment savoir, lors de la réception d'un argument de programme NULL si vous vouliez dire qu'il soit nul ou pas? Peut-être que mon code est censé pouvoir accepter des arguments nuls, mais vous pensiez que vous passais un argument non nul et d'une classe d'accord. Si vous avez utilisé un casting, vous auriez dit immédiatement. Si vous avez utilisé un comme , vous ne savez pas que vous ne connaissez que si vous essayez de faire quelque chose plus tard et que vous obtenez un résultat, vous n'attendez pas (ce qui pourrait même pas être une exception!)


@Tim Robinson - Si la référence est autorisée à être NULL, alors oui, vous voulez bien sûr utiliser comme . Dois-je mettre à jour la réponse pour clarifier cela?


Règle utile pour les nulls: traitez-les comme toxiques. Rejeter-les dans vos intrants. Évitez de les revenir en tant que sorties.


@Daniel - ce commentaire était pour @CRAIG


@Tim: les gens qui viennent de C ++ apprennent que () moulages sont mauvais et transférez ceci sur c # malgré la sémantique de casse très différente.


@Tim, parfois c'est raisonnable. Exemple courant est si vous avez implémenté Iequatable anequals () et il inclut le chèque null. Il doit inclure, puis le remplacement approprié pour objet.equals () est presque toujours correspondre égale (obj comme mytype) , à la suite du passage de NULL et d'un type différent Devrait être identique dans ce cas.


@Jon Hanna - C'est un exemple de situation où la référence cible est autorisée à être null , comme le "contrat" ​​de objet.equals est censé le gérer par conception . Le point ici n'est pas de nier l'existence de ces situations, mais qu'ils sont comparativement rares, et il est donc généralement préférable d'arrêter null s de trouver leur chemin dans les structures de données dès que possible.


Vraiment le problème sous-jacent ici est que la langue n'a aucun soutien aux références non nullables, malgré le fait que la majorité écrasante des références dans des programmes réels n'a jamais besoin de stocker la valeur null . QConlondon.com/london-2009/presentation/...


@Danielearwicker: Je n'ai pas vu la présentation, mais je suis curieux: comment les types de référence non nullables peuvent-ils fonctionner dans une langue qui ne forcent pas chaque champ de réseau ou de chaque champ de classe à écrire avant d'être lu? Si un algorithme sera en train de fonctionner correctement chaque élément de tableau avant que cet élément particulier soit lu, un échec de l'initialisation d'un élément provoque une null qui déclenche une exception semble moins susceptible de masquer un bogue que si tous les éléments de réseau ne nécessiteraient pas de pré-écrit avec une valeur "par défaut".


@supercat - L'idée est que la non-nullabilité serait un attribut optionnel d'une variable de référence, et non qu'il deviendrait obligatoire pour toutes les variables de référence. Par conséquent, un réseau ordinaire serait toujours un tableau ordinaire. Et il ne serait pas essentiel pour une langue étendue de prendre en charge des types d'éléments de tableau non nullables, voir: recherche.microsoft.com/en-us/projects/specsharp - Un tableau pourrait toujours être utilisé comme un détail de mise en œuvre interne de certains conteneurs de non-nullables.


@DanieleArwicker: Je peux voir qu'il pourrait y avoir des avantages à pouvoir déclarer qu'un emplacement de champ ou de tableau ne devrait jamais être lu quand il est null, et que si le compilateur ne peut pas confirmer de manière statique que ce ne sera pas nécessaire Générez du code pour jeter une exception si elle est [je voudrais une affectation d'un tel tableau ou d'un tel champ à une variable non nullable pour ne pas nécessiter une distribution]. Je suppose que je ne vois pas null comme un problème énorme, car, même si même si les erreurs liées à NULL ne sont pas marquées à la source, elles sont généralement marquées assez rapidement.


@DanieleArwicker: Je peux voir que de tels types pourraient être un avantage dans .NET, mais beaucoup plus utile seraient des variations sur "const ref". Avoir plusieurs types d'emplacement de stockage pour chaque type de classe, de sorte qu'une "liste dont les éléments encapsulent les identités des éléments de type Fnord" serait un type différent d'une "liste dont les éléments encapsulent les propriétés mutables des objets de type Fnord", par opposition Pour les deux choses étant une liste , aurait également été très bénéfique, mais la modernisation du cadre serait probablement plus difficile.



1
votes

Une raison définitive est que l'objet est, ou pourrait être (lors de la rédaction d'une méthode générique, vous ne savez peut-être pas que le code de codage) est jeté sur un type de valeur, auquel cas comme ISN 't permis.

Une raison plus douteuse est que vous savez déjà que l'objet est du type en question. À quel point cela dépend de la façon dont vous le savez déjà. Dans le cas suivant: xxx

Il est difficile de justifier à l'aide d'utiliser comme ici, comme la seule chose que cela fait vraiment, c'est ajouter un chèque redondant (peut-être Je serais optimisé, peut-être que ce ne sera pas). À l'autre extrême, si vous êtes à mi-chemin d'un état de transe avec la quantité d'informations que vous avez dans la mémoire de votre cercle, vous êtes à la mémoire de votre cerveau et sur la base de ce que vous êtes à peu près sûr que l'objet doit être de la Tapez en question, peut-être qu'il vaut mieux ajouter dans le chèque.

Une autre bonne raison est que la différence entre être du mauvais type et être null se cache par comme . S'il est raisonnable de passer dans une chaîne à une méthode donnée, y compris une chaîne nulle, mais il n'est pas raisonnable de passer dans un int, alors Val sous forme de chaîne vient de faire une utilisation incorrecte de l'utilisation incorrecte Différente utilisation correcte, et vous venez de rendre le virus du virus à trouver et potentiellement plus dommageable.

Enfin, peut-être que si vous ne connaissez pas le type de l'objet, le code d'appel doit. Si le code d'appel a appelé le vôtre de manière incorrecte, ils devraient recevoir une exception. Pour permettre à la invalidationnactexception de transmettre, ou de l'attraper et de lancer une exception invalidalargument ou similaire est un moyen raisonnable et clair de le faire.


1 commentaires

mytype t = obj comme mytype; Si (t! = null) {domyTypeStuff (t); } else {domoregeneralstuff (obj); }



0
votes

Telle est plus rapide et ne jette pas d'exceptions. Par conséquent, il est généralement préféré. Les raisons d'utiliser des mises comprennent:

Utiliser comme, vous ne pouvez attribuer que des types plus bas dans l'arborescence d'héritage à ceux qui sont plus élevés. Par exemple: p>

IEnumerable<T> GetList<T>(T item)
{
  (from ... select) as IEnumerable<T>
}


0 commentaires