Qu'est-ce qu'une simple instruction Noop en C #, qui ne nécessite pas l'implémentation d'une méthode? (Les méthodes Inline/Lambda sont toutefois acceptables.)
Mon cas d'utilisation actuel: je veux occuper le blocage d'un try-catch, afin de pouvoir y accéder pendant le débogage et inspecter l'exception.
Je sais que je devrais probablement gérer/consigner l’exception de toute façon, mais ce n’est pas le but de cet exercice.
Si vous voulez vraiment noop, alors cela définit une action sans nom qui ne fait rien, puis l'invoque, sans que rien ne se produise:
((Action)(() => { }))();
L'instruction vide standard/opération noop en c # est
;
un péché:
if (true)
;
cela s'adresse spécifiquement à votre cas d'utilisation (il suffit de placer un point d'arrêt sur la ligne; ou sinon d'y accéder), est minimal, et est directement pris en charge par l'environnement uniquement dans ce but (donc, même si vous faites des choses complexes , comme si vous regardiez la source compilée, vous n’auriez pas à faire de bruit supplémentaire/etc .. du compilateur/optimiseur/etc ...) - et a l’avantage supplémentaire de mettre en place un avertissement, rappelant éliminez-le de votre code lorsque vous avez terminé le débogage/le passage en production
Si vous voulez entrer dans la méthode, vous pouvez coder en dur un point d'arrêt:
System.Diagnostics.Debugger.Break();
Sinon, si vous ne compilez pas en mode release, la ligne suivante émettra un IL sur lequel vous pouvez vous connecter:
var a = 1;
Vous pouvez également écrire un Debug.Break () spécifique à votre ordinateur:
[Conditional("DEBUG")]
[Obsolete("Please remove me before checkin.")]
public static void Break()
{
#IF DEBUG
if (Dns.GetHostName() == "PROTECTORONE")
Debugger.Break();
#ENDIF
}
Notez que, à cause de [Conditional("DEBUG")]
, cette méthode ne sera pas appelée dans les sites d’appel au cours d’une construction RELEASE.
Vous pouvez écrire une fonction qui ne fait rien.
public static void Noop()
{
}
Vous pouvez simplement écrire:
catch {
;
}
L'instruction vide avec un seul point-virgule est le NOOP C #.
Que diriez-vous:
GC.KeepAlive(e);
où e
est la variable d'exception?
(Je n’ai pas essayé de mettre un point d’arrêt sur la déclaration de capture elle-même. Cela ressemble à vous devriez pouvoir le faire, précisément pour cette raison. Mais que cela fonctionne ou non, la question est différente. )
Ou un peu plus cryptiquement, en supposant que vous ayez déjà une directive using pour System.LINQ
:
"".AsEnumerable();
En plus des réponses qui répondent directement à la question.
Si vous souhaitez simplement interrompre, vous pouvez toujours placer le point d'arrêt sur le {
d'ouverture ou le }
de fermeture du bloc catch
.
Pourquoi sur-ingénierie cela?
var x = 0;
fonctionne très bien :)
L'instruction vide standard/noop en C # est
;
comme dansif (true) ;
.
- champs de bleuets
Mais si vous utilisez ce ;
standard comme branche d'une instruction if
, MS Visual Studio 2010 affiche un avertissement: "instruction vide erronée possible". (Avertissement CS0642, même si VS2010 ne me dit pas cela ni ne renvoie à l'aide réelle pour l'avertissement.)
Pire, La spécification de langage MSDN C # ne mentionne pas que codant réellement cette instruction vide en tant que branche d'une instruction if
provoque l'avertissement CS0642 "Instruction erronée possible erronée". (Attention, c'est une "mauvaise forme", potentiellement ambiguë.)
Pire encore, il semble que VS2010 ne fournisse aucun moyen de supprimer immédiatement un avertissement individuel. Je devrais insérer #pragma warning disable CS0642
avant la ou les lignes et [éventuellement] #pragma warning disable CS0642
après. Pour moi, c'est plus laid que l'avertissement. Je ferais mieux d'utiliser { }
à la place de ;
. (Je pourrais utiliser un remplacement qui est un peu moins laid.)
J'ai cherché ici un "C # no-op" parce que je voulais une alternative à la "déclaration vide", pour me débarrasser de cet avertissement. Je n'ai pas besoin d'un point de contrôle. Je veux juste une chose absolument absolue qui ne soit pas ambiguë comme "la déclaration vide".
L'alternative ne doit pas provoquer un autre avertissement. int u;
n'est pas bon car il provoque l'avertissement "La variable 'u' est déclarée mais jamais utilisée". int u = 0;
n'est pas bon car il provoque l'avertissement "La variable 'u' est affectée mais sa valeur n'est jamais utilisée".
Si noop;
(ou similaire) était ajouté en tant qu'instruction vide non ambiguë (PAS une définition de macro), ce serait formidable.
Si noop();
(ou similaire) était une fonction avec un corps vide (qui peut disparaître complètement lorsque le compilateur le met en ligne), ce serait presque bien.
Lorsque la branche est une seule déclaration, j'omets souvent les LIGNES {
et }
environnantes car elles ne sont pas nécessaires et elles étirent le code verticalement, ce qui le rend plus difficile à lire. L'incohérence dans le langage est que je ne peux pas omettre les LIGNES {
et }
environnantes lorsqu'elles entourent des instructions ZERO. Je peux compacter les deux lignes en { }
sur la même ligne, mais cela manque de cohérence. Je pense que ;
sur une ligne est la solution la plus simple et ne doit PAS provoquer un avertissement pour des motifs [non déclarés] de "mauvaise forme". Je pense que l’avertissement CS0642 aurait dû être désactivé par défaut. Je pense que le code suivant devrait être acceptable tel quel:
if (condition1)
action1;
else if (condition2)
; // (do nothing)
else if (condition3)
action3;
else if (condition4)
; // (do nothing)
else if (condition5)
action5;
else
action99;
(Je me suis plaint de ne pas pouvoir écrire ceci sous forme de commentaire car je n'avais pas encore "50 ans de réputation à commenter". Maintenant que je peux commenter, à 2K octets, il est trop long pour un commentaire de 1,5 Ko, alors ça reste ici .)
Eh bien, le NOP en C # existe, comme en C et est ';'
et sa définition correcte est " l'instruction vide ", mais pour l'usage que vous souhaitez, il est suffisant de placer le point d'arrêt dans le crochet de fermeture ... .____.] Il n’est pas nécessaire de garder Keep Alive complet, car la durée de vie d’une référence à un objet dans une méthode est étendue à la fin de la méthode lorsque le débogueur est attaché. Donc vous avez simplement besoin d'écrire
catch(Exception exception)
{
}
et placez le point d'arrêt sur le crochet de fermeture et consultez le contenu de l'exception.
Je sais que c'est une vieille question et, techniquement, cette réponse ne concerne pas le cas d'utilisation du demandeur. Cependant, il existe une instruction NOOP dans CIL, qui est nop
. A titre expérimental, prenons l’application CIL suivante.
.Assembly extern mscorlib {}
.Assembly Test
{
.ver 1:0:1:0
}
.module test.exe
.method static void main() cil managed
{
.maxstack 1
.entrypoint
nop
nop
nop
nop
ret
}
Si vous compilez l'application et que vous la décompilez avec un outil tel que ILSpy, en C #, voici le contenu de la méthode main ():
static void main()
{
}
Comme vous pouvez le constater, il n'y a rien là-bas. Toutefois, si nous voulons vérifier que le compilateur CIL n'a pas optimisé ces instructions nop
, nous pouvons afficher notre application dans le code IL décompilé dans ILSpy et voici ce que nous voyons pour la méthode principale:
.method static privatescope
void main$PST06000001 () cil managed
{
// Method begins at RVA 0x2050
// Code size 5 (0x5)
.maxstack 1
.entrypoint
IL_0000: nop
IL_0001: nop
IL_0002: nop
IL_0003: nop
IL_0004: ret
} // end of method '<Module>'::main
CIL est en train de compiler les instructions nop
dans l’Assemblée. C # n'ayant aucune implémentation de cette instruction, ces commandes nop
ne sont pas affichées dans le code C # désassemblé.
Je n'ai pas de licence pour Reflector, mais j'imagine que si vous décompiliez ces binaires avec Reflector, vous obtiendrez une sortie similaire pour C #.
Essayez-vous de déboguer une version (optimisée)? C'est normalement l'optimiseur qui supprime les variables non référencées et les blocs vides.
Deux solutions:
catch
et utilisez $exception
- créé par le débogueur pour référencer l'exception en vol - dans la fenêtre de l'outil Locals.Ceci est un ajout à la réponse de @AHM, car je voulais un moyen facile de faire du NOOP à des fins de débogage (communiquer avec AB PLC CompactLogix et avoir des erreurs uniquement visibles dans Disassembly à cause de la bibliothèque C++ DLL import dans C #).
J'ai pris le one-liner
((Action)(() => { }))();
et placez-le dans un extrait nomménoop.snippetpuis placez-le dans le dossier intitulé Mes extraits de code.
(Outils -> Gestionnaire d'extraits de code -> Emplacement) OR Accord (Ctrl + K, Ctrl + B)
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.Microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>noop</Title>
<Shortcut>noop</Shortcut>
<Description>Code snippet to inject an Assembly (x86) equivalent of the NOOP command into the code's disassembly.</Description>
<Author>Jay Whaley</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Code Language="csharp">
<![CDATA[// Forces a psuedo NOOP in disassembly
((Action)(() => { }))();
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
Cela aide à en faire un raccourci d’utilisation rapide au cas où la communication de bas niveau s’embrouille et nécessite que cela soit une tactique de débogage courante. L'assembly réel généré est le suivant, mais il y a quelques articles sur la façon d'utiliser Assembly réel inline en C #.
Solution fiable
try
{
blablablablaStatemnt();
}
catch(Exception ex)
{
#IF DEBUG
Debugger.Break();
#END IF
}
Aussi simple que ça!
Autrement
peut être très utile