I am trying to get to grips with C# having not coded for many years and my previous experience being in ANSI C.
I have read a number of books and searched online but one aspect is evading me and I am hoping someone here can help.
In the past I would declare a function and if there was a possibility of something not happening within the function (i.e. file not found etc.) declare the return to be an integer. I would then return 0 if all was well and a value if not. The value would correspond to where the function failed to execute fully and I could branch accordingly from where I called it.
if(function1())
{
// all my error stuff, maybe a switch/case etc.
}
All the examples I have found in C# seem to avoid this technique and I was hoping to get some understanding here.
Thanks in anticipation.
(I know I am a fossil). :)
Exceptions are the approach you use in C# and similar languages.
It goes like this:
try
{
function();
}
catch(FileNotFoundException e)
{
// File not found
}
catch(UnauthorizedAccessException e)
{
// User doesn't have right to access file
}
// etc...
To make this work, function shouldn't return a status code but instead throw an exception in case of an error.
Please note that the exceptions I illustrated in the code block above are thrown by the framework if you try to access a file and one of those errors is happening. So you don't actually have to do this yourself.
Furthermore, in C# there is no implicit conversion from integral values to bool, i.e. if(function()) is invalid, if function returns an int. You would need to write it like this:
if(function() != 0)
{
// all your error stuff
}
There's nothing to stop you doing this (though there are better ways of handling the errors - exceptions for example).
If you do want to carry on with this approach, the biggest problem you are having is that in C# you can't treat an integer as a boolean so your if test won't compile. What you need is:
if (function1() != 0)
{
}
But to check the value you'd need:
int result = function1();
switch (result)
{
case 1:
// Handle this case
break;
case 2:
// Handle this case
break;
default:
// All OK
break;
}
It would be better to return an enumerated type for each error case so that you don't have magic numbers, but exceptions are the way to go:
try
{
function1();
}
catch (SpecificException1 e1)
{
// Handle this case
}
catch (SpecificException2 e2)
{
// Handle this case
}
What you shouldn't have is a general exception handler:
catch (Exception e)
{
}
This just hides other potential problems.
If you want to follow that pattern of checking return value instead of managing errors, you better use enumarations than plain numbers.
For example:
public enum ResultType
{
Error = 0,
Success,
Waiting
}
public ResultType function()
{
if (still_waiting)
return ResultType.Waiting;
if (error_has_occured)
return ResultType.Error;
return ResultType.Success;
}
public void Main()
{
ResultType result = function();
switch (result)
{
case ResultType.Success:
MessageBox.Show("all is good");
break;
case ResultType.Waiting:
MessageBox.Show("still waiting...");
break;
case ResultType.Error:
MessageBox.Show("error has occurred");
break;
}
}
Behind the scenes, it's still using numbers but you put some meaning to each number.
if(function()==1)
{
}
int function()
{
int returnVal =0;
// do stuff
// if true return returnVal =1 else set returnVal =0;
return returnVal;
}
Related
I am using Visual Studio 2019, and I have a piece of code that uses finally block, I have declared a std::string object at the beginning of each Test1(), Test2() and Test3() functions.
I put a break point inside the finally block of each function to see the str variable, and as a result the str variable is reset to Empty in the Test1() and Test2() functions. Only in Test3() function is not reset.
I discovered that str is reset if a return statement is encountered before entering the finally block.
I don't understand what is going on, in the code of my software there are many places where finally block is used like the example above, I need to understand the exact mechanism of it so that I can fix potential bugs in the application.
The following is the code of the Test functions
void Test1()
{
string str = "Test1";
try
{
int* i = NULL;
*i = 0; //This command will raise an exception
return;
}
catch (Exception^ e)
{
return;
}
finally
{
int i = 0; //'str' is rested as empty when entering here
}
}
void Test2()
{
string str = "Test2";
try
{
int* i = NULL;
return;
}
catch (Exception^ e)
{
return;
}
finally
{
int i = 0; //'str' is rested as empty when entering here
}
}
void Test3()
{
string str = "Test3";
try
{
int* i = NULL;
}
catch (Exception^ e)
{
}
finally
{
int i = 0; //'str' is NOT reset to empty when entering here
}
}
Thank you so much!
I debug and double check, found that destructor of local variables will be destroyed when encountering return statement, destructor is called before entering finally block. Only if no return statement is encountered will these destructors be called after the Finally block (regardless of whether an exception occurs or not).
Due to this inconsistency, I could only work around it by not using any finally blocks in the code anymore, replacing it with goto statements or equivalent.
P/S: I am configuring the project with SEH Exceptions (/EHa) option.
For example, consider the following C# code:
interface IBase { void f(int); }
interface IDerived : IBase { /* inherits f from IBase */ }
...
void SomeFunction()
{
IDerived o = ...;
o.f(5);
}
I know how to get a MethodDefinition object corresponding to SomeFunction.
I can then loop through MethodDefinition.Instructions:
var methodDef = GetMethodDefinitionOfSomeFunction();
foreach (var instruction in methodDef.Body.Instructions)
{
switch (instruction.Operand)
{
case MethodReference mr:
...
break;
}
yield return memberRef;
}
And this way I can find out that the method SomeFunction calls the function IBase.f
Now I would like to know the declared type of the object on which the function f is called, i.e. the declared type of o.
Inspecting mr.DeclaringType does not help, because it returns IBase.
This is what I have so far:
TypeReference typeRef = null;
if (instruction.OpCode == OpCodes.Callvirt)
{
// Identify the type of the object on which the call is being made.
var objInstruction = instruction;
if (instruction.Previous.OpCode == OpCodes.Tail)
{
objInstruction = instruction.Previous;
}
for (int i = mr.Parameters.Count; i >= 0; --i)
{
objInstruction = objInstruction.Previous;
}
if (objInstruction.OpCode == OpCodes.Ldloc_0 ||
objInstruction.OpCode == OpCodes.Ldloc_1 ||
objInstruction.OpCode == OpCodes.Ldloc_2 ||
objInstruction.OpCode == OpCodes.Ldloc_3)
{
var localIndex = objInstruction.OpCode.Op2 - OpCodes.Ldloc_0.Op2;
typeRef = locals[localIndex].VariableType;
}
else
{
switch (objInstruction.Operand)
{
case FieldDefinition fd:
typeRef = fd.DeclaringType;
break;
case VariableDefinition vd:
typeRef = vd.VariableType;
break;
}
}
}
where locals is methodDef.Body.Variables
But this is, of course, not enough, because the arguments to a function can be calls to other functions, like in f(g("hello")). It looks like the case above where I inspect previous instructions must repeat the actions of the virtual machine when it actually executes the code. I do not execute it, of course, but I need to recognize function calls and replace them and their arguments with their respective returns (even if placeholders). It looks like a major pain.
Is there a simpler way? Maybe there is something built-in already?
I am not aware of an easy way to achieve this.
The "easiest" way I can think of is to walk the stack and find where the reference used as the target of the call is pushed.
Basically, starting from the call instruction go back one instruction at a time taking into account how each one affects the stack; this way you can find the exact instruction that pushes the reference used as the target of the call (a long time ago I wrote something like that; you can use the code at https://github.com/lytico/db4o/blob/master/db4o.net/Db4oTool/Db4oTool/Core/StackAnalyzer.cs as inspiration).
You'll need also to consider scenarios in which the pushed reference is produced through a method/property; for example, SomeFunction().f(5). In this case you may need to evaluate that method to find out the actual type returned.
Keep in mind that you'll need to handle a lot of different cases; for example, imagine the code bellow:
class Utils
{
public static T Instantiate<T>() where T : new() => new T();
}
class SomeType
{
public void F(int i) {}
}
class Usage
{
static void Main()
{
var o = Utils.Instantiate<SomeType>();
o.F(1);
}
}
while walking the stack you'll find that o is the target of the method call; then you'll evaluate Instantiate<T>() method and will find that it returns new T() and knowing that T is SomeType in this case, that is the type you're looking for.
So the answer of Vagaus helped me come up with a working implementation.
I published it on github - https://github.com/MarkKharitonov/MonoCecilExtensions
Included many unit tests, but I am sure I missed some cases.
(In case you're interested, the background for this question is here, but I don't think it's critical for this particular question.)
We're trying to run a series of report exports (a third party method call) one at a time in separate threads, so we can kill off the thread if it takes too long. The ugly, but best-so-far, idea is to use Thread.Abort to kill the thread exporting a given report, then do a ResetAbort to allow the rest of the code to continue.
The proof of concept code looks like this:
public RunningMethod()
{
Report myReport = new Report();
for (int i = 0; i < 10; i++)
{
Thread reportThread = new Thread(() => DoBackgroundJob(myReport, "test" + i.ToString()));
reportThread.Start();
bool finished = reportThread.Join(TimeSpan.FromMilliseconds(100));
if (!finished)
{
reportThread.Abort();
}
}
}
protected void DoBackgroundJob(Report myReport, string reportFilename)
{
try
{
report.ExportToPdf(#"C:\" + reportFilename + ".pdf");
}
catch (ThreadAbortException)
{
}
break;
}
I'm getting a strange result when I run this...the Export line seems to throw an exception that seems like it should be a ThreadAbortException, but apparently is not, since it doesn't get caught by the catch (ThreadAbortException), but is caught by a catch (Exception).
I'd like to know what kind of exception I'm getting, but I can't see it because when I try to view it I only get "Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack."
Is there a way to determine what is happening? What exception is really being thrown here?
Here is a very strange thing which I don't think should happen:
UnicodeString test = "abc";
try
{
try
{
int a = 123;
return a; // This seems to produce a problem with "test" variable scope
}
catch (Exception &e)
{
// Some exception handler here
}
}
__finally
{
// At this point the "test" variable should still be in scope???
test = "xyz"; // PROBLEM here - test is NULL instead of "abc"! Why?
}
If I remove the return a; in the try-catch block the test variable is still defined. Is there a particular reason why after the above construct the UnicodeString seems to go out of scope? Is it a bug with C++ Builder 2010? I understand that return returns from function but it should still retain variable scope in the __finally block shouldn't it?
I did a bit more analysis and it seams that once you execute return statement all local objects from stack are acting as destroyed. If you try using heap objects instead this won't happen.
UnicodeString *test = new UnicodeString("abc");
try
{
try
{
int a = 123;
return a; // This seems to produce a problem with "test" variable scope
}
catch (Exception &e)
{
// Some exception handler here
}
}
__finally
{
ShowMessage(*test); // "abc"
*test = "xyz";
}
delete test;
Using smart pointers like unique_ptr will again result in loosing an object in __finally since return will initiate it's destruction.
(Remy posted this in comments but did not post an answer here)
When a return statement is hit within a try...finally block, what happens is that any local objects are destroyed (as they would be for any other return) before the __finally block is entered.
So by the time your code gets up to test = "xyz";, test has already been destroyed, causing undefined behaviour.
I guess it is a matter of semantics whether you call this a bug or a design flaw, but either way it is something to bear in mind when using try...finally. My personal advice would be to just not use it at all; the Standard C++ techniques of try...catch and RAII can solve any problem.
It's not critical but I was wondering. Somewhere in my program I have a switch statement that gets called multiple times with an incremented value, so that all cases should be executed in order. Something like a custom made simple sequencer.
like this:
private function sequence_Crush(step:Int):Void
{
switch(step) {
case 1: {
action_loadCueFile();
seq.next(); //This calls the same function with an increased step
}
case 2: {
action_saveSettings();
seq.next();
}
/// EDIT: Some steps run ASYNC and an event triggers the next step in the sequence
/// like this:
case 3: {
events.once(ENGINE_EVENTS.cut_all_complete, seq.next);
cutTracks();
}
My Question is, Is there any way to replace the manually written numbers (1,2,3,4) on the cases and use a counter somehow, macros maybe? I have tried putting a dynamic counter, but the Haxe compiler complains.
What I tried:
var st:Int = 1;
switch(step) {
case (st++): { // 1
action_loadCueFile();
seq.next();
}
case (st++): { // 2
action_saveSettings();
seq.next();
}
//... etc
Build halted with errors (haxe.exe)
Case expression must be a constant value or a pattern, not an arbitrary expression
I am targeting JS and using Haxe 3.1.3. I have tried that in actionscript and javascript and it works fine. The reason I want to do that, is that if I want do add or remove a step, I have to re-organize manually every other case number.
p.s. I know there are other ways to sequence actions in order, but I like this one, as I have everything in one function and it's easy to see the order of execution in one glance
Thanks for reading :-)
Jason beat me to it by a few minutes...
Case expressions in Haxe must be either constant values or patterns.
But you can accomplish the desired behaviour in a few ways: (a) custom syntax like $next with macros; (b) macro conversion into if-else blocks (Jason's answer); (c) without macros and (mis)using pattern guards.
Custom syntax
A quick and dirty implementation of it follows; it only supports case $next: and there are no syntax checks.
When a case $next: is found, the macro checks if the previous case pattern was a single constant integer i and, in that case, rewrites the pattern to the value of i + 1.
Macro implementation:
// SequenceSwitch.hx
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.ExprTools;
class SequenceSwitch {
public
macro static function build():Array<Field> {
var fields = Context.getBuildFields();
for (f in fields)
switch (f.kind) {
case FFun(func) if (func.expr != null):
func.expr = ExprTools.map(func.expr, transf);
case _:
}
return fields;
}
static function transf(e:Expr):Expr {
return switch (e.expr) {
case ESwitch(expr, cases, def):
var ncases = [];
var prev:Array<Expr> = null;
for (c in cases) {
var cur = switch (c.values) {
case [{ expr : EConst(CIdent("$next")), pos : pos }] if (prev != null):
switch (prev) {
case [{ expr : EConst(CInt(i)) }]:
var next = { expr : EConst(CInt(Std.string(Std.parseInt(i) + 1))), pos : pos };
{ values : [next], guard : c.guard, expr : c.expr };
case _:
c;
}
case _:
c;
};
ncases.push(cur);
prev = cur.values;
}
{ expr : ESwitch(expr, ncases, def), pos : e.pos };
case _:
e;
}
}
}
Usage example:
// Text.hx
#:build(SequenceSwitch.build())
class Test {
static function main() {
sequenceCrush(1);
}
static function sequenceCrush(step:Int) {
switch (step) {
case 1:
trace("do one");
sequenceCrush(++step);
case $next:
trace("do two");
sequenceCrush(++step);
case $next:
trace("do three");
sequenceCrush(++step);
case _:
trace("terminate");
}
}
}
No macros/with guards
Similar behaviour could be achieved by (mis)using guards:
static function sequenceCrush_guards(step:Int) {
var st = 1;
switch (step) {
case next if (next == st++):
trace("do one");
sequenceCrush_guards(++step);
case next if (next == st++):
trace("do two");
sequenceCrush_guards(++step);
case next if (next == st++):
trace("do three");
sequenceCrush_guards(++step);
case _:
trace("terminate");
}
}
In Haxe 3 switch changed from the JS/Flash style simple matching, which was really not much more than a chain of if/elseif/else statements, to full on pattern matching, which has many more compile-time features, and one of those limitations is that you can't match against a variable, only against constants.
You could use a chain of if (step==st++) {} elseif (step==st++) {} else {} statements for pretty much the same effect. If you're really really addicted to the switch syntax, you could use a macro to get the "classic" switch behaviour. I happened to write one such macro some time ago, take a look at this GIST:
https://gist.githubusercontent.com/jasononeil/5429516/raw/ad1085082530760aa394765d5cd5ebd61a5dbecb/ClassicSwitch.hx
You could then code like this:
class Action
{
static function main()
{
for (currentStep in 0...5) {
var i = 0;
ClassicSwitch.from(switch (currentStep) {
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
});
}
}
}
Which gives me the output:
Action.hx:14: Do step 1
Action.hx:15: Do step 2
Action.hx:16: Do step 3
Action.hx:17: Do step 4
Action.hx:18: Do step 5
If all (or most) of your actions are simple function calls you can alternatively use an array of functions:
var actions = [sequence_Crush.bind(1), // if you want to avoid action index = step - 1
action_loadCueFile,
action_saveSettings,
...];
private function sequence_Crush(step:Int):Void
{
while (step < actions.length)
{
actions[step++]();
}
}
You could also keep this recursive (actions[step++](); if (step < actions.length) { sequence_Crush(step)).