C# Puzzle : Reachable goto pointing to an unreachable label - c#

Here's Eric Lippert's comment from this post:
Now that you know the answer, you can
solve this puzzle: write me a program
in which there is a reachable goto
which goes to an unreachable label. –
Eric Lippert Jul 17 at 7:17
I am not able to create a code which will have reachable goto pointing to an unreachable label. Is that even possible? If yes, what would the C# code look like?
Note: Let's not get into discussion about how 'goto' is bad etc. This is a theoretical exercise.

My original answer:
try
{
goto ILikeCheese;
}
finally
{
throw new InvalidOperationException("You only have cottage cheese.");
}
ILikeCheese:
Console.WriteLine("MMM. Cheese is yummy.");
Here is without the compiler warning.
bool jumping = false;
try
{
if (DateTime.Now < DateTime.MaxValue)
{
jumping = (Environment.NewLine != "\t");
goto ILikeCheese;
}
return;
}
finally
{
if (jumping)
throw new InvalidOperationException("You only have cottage cheese.");
}
ILikeCheese:
Console.WriteLine("MMM. Cheese is yummy.");

By the way if you use goto the csharp compiler for example for this case without finally block changes the code to a version without goto.
using System;
public class InternalTesting
{
public static void Main(string[] args)
{
bool jumping = false;
try
{
if (DateTime.Now < DateTime.MaxValue)
{
jumping = (Environment.NewLine != "\t");
goto ILikeCheese;
}
else{
return;
}
}
finally
{
if (jumping)
{
//throw new InvalidOperationException("You only have cottage cheese.");
Console.WriteLine("Test Me Deeply");
}
}
ILikeCheese:
Console.WriteLine("MMM. Cheese is yummy.");
}
}
Turns To:
public static void Main(string[] args)
{
bool flag = false;
try
{
if (DateTime.Now < DateTime.MaxValue)
{
flag = Environment.NewLine != "\t";
}
else
{
return;
}
}
finally
{
if (flag)
{
Console.WriteLine("Test Me Deeply");
}
}
Console.WriteLine("MMM. Cheese is yummy.");
}

goto cant_reach_me;
try{
cant_reach_me:
}
catch{}
This is either a compile or runtime error, I can not remember. The label must be outside the try/catch block

Related

How to decompile a specific method generating the same code when decompiled via DecompileTypeAsString

NOOB with ILSPY
I'm trying to decompile a method via ILSpy. When I use the following, I get the code re-generated that is pretty close to what was typed in the original C#
decompiler.DecompileTypeAsString(new FullTypeName($#"{MyFullTypeName}"));
The generated code looks something like follows.
public async Task<IReadOnlyList> FuncName(parameterList)
{
//Actual code body
}
Whereas when I use the following snippet,
string functionName = "ReflectionNamed__5";
var name = new FullTypeName(functionName);
ITypeDefinition typeInfo = decompiler.TypeSystem.MainModule.Compilation.FindType(name).GetDefinition();
if (typeInfo.Methods.First().HasBody)
{
var tokenOfFirstMethod = typeInfo.Methods.First().MetadataToken;
var methodCodeString = decompiler.DecompileAsString(tokenOfFirstMethod);
Console.WriteLine(methodCodeString);
}
The code generated is as following:
//Using statements
private void MoveNext()
{
int num = <>1__state;
IReadOnlyList<string> result;
try
{
if (num != 0)
{
//Abstraction of a using statement
}
try
{
TaskAwaiter<IReadOnlyList<string>> awaiter;
if (num != 0)
{
//Somewhat resembles the actual code
}
else
{
awaiter = <>u__1;
<>u__1 = default(TaskAwaiter<IReadOnlyList<string>>);
num = (<>1__state = -1);
}
result = awaiter.GetResult();
}
finally
{
if (num < 0 && <oLogger>5__2 != null)
{
<oLogger>5__2.Dispose();
}
}
}
catch (Exception exception)
{
<>1__state = -2;
<>t__builder.SetException(exception);
return;
}
<>1__state = -2;
<>t__builder.SetResult(result);
}
Is there a way to generate the code as generated by DecompileTypeAsString by decompiling only one function?
I filed an issue on ILSpy and it has been marked as enhancement. So guess it isn't possible at the moment.
I'll go the ugly regex route for now and check back in on the enhancement in later versions.
https://github.com/icsharpcode/ILSpy/issues/1935

How to keep checking if a user presses esc while Reading lines?

I want to keep reading lines of the user, but when this user presses on escape I want it to stop. But how can I keep reading single keys (for the escape), while meanwhile reading lines? I hope the question will be more clear after giving my code:
int number;
do
{
string a = Console.ReadLine();
try
{
Int32.TryParse(a, out number);
}
catch
{
Console.WriteLine("I only accept int");
}
finally
{
Console.Writeline(number);
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
as you have written, you want to read lines until escape is pressed, but as your code says, you want to read only integers. Here's what I think is what you want,
int number = 0;
do
{
while (!Console.KeyAvailable)
{
string a = Console.ReadLine();
bool bWriteNumber = false;
try
{
number = int.Parse(a);
bWriteNumber = true;
}
catch
{
Console.WriteLine("Sorry! I only accept int");
}
finally
{
if (bWriteNumber)
Console.WriteLine(number);
}
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
I am not sure to understand completely your question but you can test the code below if it matches your requirements
using System;
using System.Globalization;
namespace StackOverflow_31111668
{
class Program
{
static void Main()
{
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
{
var a = Console.ReadLine();
int number;
Console.WriteLine(!int.TryParse(a, out number) ? "I only accept int" : number.ToString(CultureInfo.InvariantCulture));
}
}
}
}

skip a for-loop but from function which is called inside that loop in c#

hey guys m running into a problem, i have a forloop n in that i call a function, and in that function i have a if condition, i want to skip 1 loop if condition gets true, for this problm i was thinkin' to use goto statement but as i read in many forums that goto statement is an evil... can it be solved without using goto statement, ne ideas i dn't want to use 'goto'
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
aFunction(param1,param2);
}
public void aFunction(param1,param2)
{
//some operation;
if (!Regex.IsMatch(RechargeText, "successfully"))
{
RechargeStatus = "Failed";
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_error.wav";
Program.sp.Play();
}
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
// here i need to skip the Loop
}
else
{
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
}
Actually there are some error list that are accepted errors, so i dn't need to update that in db, So my TextFill(); function shud not run for accepted errors
Snippet Edited
Simple, have the method return a bool. Then you can do:
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
if (aFunction(param1,param2)) break;
}
goto won't help you anyway. Basically you can't continue from a different method at all. The only simple way you can keep roughly your current flow is something like this:
bool shouldSkipNext = false;
for (int i = 0; i < gridview.Rows.Count - 1; i++)
{
if (shouldSkipNext)
{
shouldSkipNext = false;
continue;
}
// some operation
shouldSkipNext = aFunction(param1, param2);
}
public bool aFunction(param1,param2)
{
if (abc)
{
return true;
}
// Other stuff
return false;
}
Note that this will skip the entirety of the next iteration of the loop - which isn't the same as just continue. If you have more code after the call to aFunction and you want to skip that (which is the equivalent of continue) then it's simpler:
for (int i = 0; i < gridview.Rows.Count - 1; i++)
{
// some operation
if (aFunction(param1, param2))
{
continue;
}
// Other stuff which will sometimes be skipped
}
All you want to do is skip executing the TextFill() function when the condition if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not")) is true, thats all right?
You can simply return at that if condition, which will work out as you want:
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
return;
} .... // rest of the code as it is
now when the above condition works out as true it will return to the for loop and go with the next iteration and so on...
Cheers
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
if (!aFunction(param1,param2)) continue;
}
public bool aFunction(param1,param2)
{
//some operation;
if (!Regex.IsMatch(RechargeText, "successfully"))
{
RechargeStatus = "Failed";
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_error.wav";
Program.sp.Play();
}
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
Program.StatusMessage = "Recharge Successful";
TextFill();
return false;
// here i need to skip the Loop
}
else
{
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
return true;
}
If your code as posted is exactly how it is, then you could simply return, as the loop has no other operations.
No, it can not be solved with a goto... thankfully.
There is nothing that you can do inside the method that will change the control flow in the loop, you have to return something from the method and use that in the code of the loop:
for(int i = 0; i < gridview.rows.count - 1; i++) {
//some operation;
if (aFunction(param1,param2)) {
// do something more here
}
}
public bool aFunction(param1,param2) {
//some operation;
if(abc) {
//skip the current for-loop i.e i want to do "continue" here;
return false;
} else {
//normal
return true;
}
}
public static void main(String[] args) {
int param1 = 0, param2 = 0;
getResult(param1, param2);
}
public static void getResult(Object param1, Object param2) {
for (int i = 0; i < gridview.rows.count - 1; i++) {
if (!Regex.IsMatch(RechargeText, "successfully")) {
RechargeStatus = "Failed";
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_error.wav";
Program.sp.Play();
} else if (Regex.IsMatch(RechargeText, "Processing")
|| Regex.IsMatch(RechargeText, "Not")) {
// just skip here then
continue;
} else {
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
}
}
You should extract
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_success.wav";
Program.sp.Play();
and
RechargeStatus = "Failed";
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_error.wav";
Program.sp.Play();
into its own methods to make this code clearer, looks like a mess.

Is this goto expressive?

The following code was a proof of concept for a message batching routine. Do I avoid goto like the plague and rewrite this code? Or do you think the goto is an expressive way to get this done?
If you'd rewrite please post some code...
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
HaveAnotherMessage:
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
{
goto HaveAnotherMessage;
}
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
// queue processing code
}
Pretty much sums up my thoughts on "goto."
Goto is bad programming practice for many reasons. Chief among them is that there is almost never a reason for it. Someone posted a do..while loop, use that. Use a boolean to check if you should continue. Use a while loop. Goto's are for interpreted languages and a call back to assembler days (JMP anyone?). You're using a high level language for a reason. So that you and everyone else doesn't look at your code and get lost.
To keep this answer somewhat current I'd like to point out that a combination of goto and bracing errors caused a major SSL bug in iOS and OS X.
Replace the goto with a do-while, or simply a while loop if you don't want the "always run once" functionality you have right now.
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
do {
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
} while(queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
// queue processing code
}
It's so amazingly easy to rid yourself of GOTO in this situation it makes me cry:
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
bool hasAnotherMessage = true
while(hasAnotherMessage)
{
hasAnotherMessage = false;
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
{
hasAnotherMessage = true;
}
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
}
// queue processing code
}
I guess the goto is SLIGHTLY more readable intuitively... But if you WANTED to avoid it I think all you'd have to do is throw the code in a while(true) loop, and then have a break statement at the end of the loop for a normal iteration. And the goto could be replaced with a continue statement.
Eventually you just learn to read and write loops and other control flow structures instead of using goto statements, at least in my experience.
Kind of related to Josh K post but I'm writing it here since comments doesn't allow code.
I can think of a good reason: While traversing some n-dimensional construct to find something. Example for n=3 //...
for (int i = 0; i < X; i++)
for (int j = 0; j < Y; j++)
for (int k = 0; k < Z; k++)
if ( array[i][j][k] == someValue )
{
//DO STUFF
goto ENDFOR; //Already found my value, let's get out
}
ENDFOR: ;
//MORE CODE HERE...
I know you can use "n" whiles and booleans to see if you should continue.. or you can create a function that maps that n-dimensional array to just one dimension and just use one while but i believe that the nested for its far more readable.
By the way I'm not saying we should all use gotos but in this specific situation i would do it the way i just mentioned.
You could refactor is to something like this.
while (queue.Count < this.batch && buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
buffer = null;
if (item != null)
{
queue.Enqueue(item);
socket.Recv(out buffer, ZMQ.NOBLOCK)
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
Umm, I'm not really sure you want to goto out of a try block. I'm pretty sure that is not a safe thing to do, though I'm not 100% sure on that. That just doesn't look very safe...
Wrap the "HaveAnotherMessage" into a method that takes in the buffer and may call itself recursively. That would seem to be the easiest way to fix this.
I would avoid goto in this case, and refactor it. The method reads too long in my opinion.
I think your method is too big. It mixes different levels of abstraction, like error processing, message retrieval and message processing.
If you refactor it in different methods, the goto naturally goes away (note: I assume your main method is called Process):
...
private byte[] buffer;
private Queue<TraceItem> queue;
public void Process() {
queue = new Queue<TraceItem>(batch);
while (connected) {
ReceiveMessage();
TryProcessMessage();
}
}
private void ReceiveMessage() {
try {
socket.Recv(out buffer);
}
catch {
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the processing
}
}
private void TryProcessMessage() {
try {
ProcessMessage();
}
catch (Exception ex) {
ProcessError(ex);
}
}
private void ProcessMessage() {
if (buffer == null) return;
var item = TraceItemSerializer.FromBytes(buffer);
if (item == null) return;
queue.Enqueue(item);
if (HasMoreData()) {
TryProcessMessage();
}
}
private bool HasMoreData() {
return queue.Count < batch && socket.Recv(out buffer, ZMQ.NOBLOCK);
}
private void ProcessError(Exception ex) {
ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
tracer.TraceException(TraceEventType.Error, 0, ex);
}
...

If else block creating problem

I have a piece of code where in I have an if block which when satisfied the flow goes into it and in there are nested if and else, if it does not satisfies any of the if block it should go into the else block but the problem i am facing is that it satisfies one if block and then goes into else as well. this is creating redundancy in my code.
it like this
if(condition = true)
{
if(condition1 == true)
{}
if(condition2 == true)
{}
else
{}
}
Now it satisfies condition 1 and then after performing if block operations goes into else also.
Please help. Code is in C#
You probably need something like this (notice else if with condition2):
if(condition)
{
if(condition1)
{}
else if(condition2)
{}
else
{}
}
You can skip '== true' in conditions.
get rid of the ==true's its just going to lead to a mistake like you made on the first line. also, add in else statements.
if (condition)
{
if (condition1)
{ }
else if (condition2)
{ }
else
{ }
}
As RaYell says, you need an extra "if" block. Here's a short but complete example to demonstrate:
using System;
public class Test
{
static void Main()
{
bool condition = true;
bool condition1 = true;
bool condition2 = false;
if (condition)
{
if (condition1)
{
Console.WriteLine("condition1");
}
// Note the "else if" here.
else if (condition2) {
Console.WriteLine("condition2");
}
else
{
Console.WriteLine("neither");
}
}
}
}
This prints "condition1" but not "neither".
If that isn't what you want, please clarify your question.
Put it like this
if(condition == true) {
if(condition1 == true) {}
else if(condition2 == true) {}
else {}
}
Ya you can use else if.Also you can write
if (condition==true) as if(condition) simply
For example
int i=2;
int j=3;
int k=4;
bool condition=k>1;
bool condition1=j<i;
bool condition2=j>i;
if (condition)
{
if (condition1)
{ }
else if (condition2)
{ }
else
{ }
}
Then, why don't you split up your code in methods, so you can do this:
if( condition)
{
if( condition1 )
{
DoSomethingForSituation1();
}
else
{
DoSomethingForSituation2();
}
}
else
{
DoSomethingForSituation1();
}
Also, when I look at it this way, you could say that 'condition' is redundant ?
Because either way, condition1 will always be true in some scenario ?
if( condition1 )
{
DoSomethingForSituation1();
}
else if( condition2 )
{
DoSomethingForSituation2();
}

Categories

Resources