I just ran into a weird scope issue with method parameters in C# and I was wondering if anyone could shed some light on why this is happening or whether it's a bug.
My code essentially is this:
void MyMethod(SqlHelper db, int myInt)
{
try
{
using (db)
{
var bar = OtherMethod(myInt);
On the last line, myInt is throwing an error: "Cannot use local variable 'myInt' before it is declared"
This doesn't throw an error:
void MyMethod(SqlHelper db, int myInt)
{
try
{
var foo = myInt;
using (db)
{
And my workaround for now is:
void MyMethod(SqlHelper db, int myInt)
{
var foo = myInt;
try
{
using (db)
{
var bar = OtherMethod(foo);
But why is this happening? How is myInt falling outside of the scope of the using statement?? I feel personally attacked.
My project is in .Net Framework 4.7.
EDIT: I can't actually reproduce this with the slimmed down version I presented. I will do more research. Thanks to everyone who helped.
EDIT 2: As everyone noted, I left out too much information and the error couldn't be replicated. I found the issue and will leave it here because I am dumb and maybe it will help someone.
Relevant code was this:
void MyMethod(SqlHelper db, int myInt)
{
try
{
using (db = new SqlHelper())
{
var bar = OtherMethod(myInt);
var myInt = SomeMethod(bar);
I had declared another variable with the same name further down within the using statement and Visual Studio didn't like that but didn't know how to tell me. What a day. Thanks again to everyone who came with me on this journey.
I've tried to reproduce the error but was not successful, meaning the unit test that I created works. It compiles and it does not throw any exception. Thus, you would have to provide some more information for us to reproduce the error.
private void MyMethod(IDisposable db, int myInt)
{
try
{
using (db)
{
int bar = OtherMethod(myInt);
}
}
catch (Exception ex)
{
// Do something with the exception.
throw;
}
}
private int OtherMethod(int myInt)
{
return myInt;
}
[Fact]
public void Test1()
{
MyMethod(new MemoryStream(), 10);
}
Note that passing the SqlHelper as a parameter and then putting that in theusing statement is not a good practice. You should avoid that.
One very odd thing you are doing is withyour using statement. You are putting a using on db, an object that someone else has created and passed into this method. When the code leaves your using block it will be disposed and whoever created it will not be able to use it, even though the expect to.
Generally objects should be put in a using block when they are created:
using (var db = new SqlHelper())
{
...
}
Not sure if that's the cause of you're problem, though.
Related
We have a piece of code that previously worked fine and now it gets stuck, the problem seems to be runtime updates or something like it maybe?
We launch a subthread that shows a Form Dialog and gets a value, this value is returned to the main thread by a static variable in an static class and in that statement the thread gets stuck and visual studio doesn't say anything about what's happening... is there another way to return the value (in some cases there are more than one string to return)
We need to do this way specifically because of how the software we do the add-on programs for work.
Example code:
public static Cons
{
public static string inputvalue;
}
public static Funs
{
public static string GetValueString()
{
Thread threadx = new Thread(GetValueStringx);
threadx.SetApartmentState(ApartmentState.STA);
threadx.Start();
if (threadx.Join(new TimeSpan(0, 3, 0)))
{
return ComprobarLicencia(Cons.inputvalue);
}
/*because the subthread is stuck the wait time (3mins) is always
reached and the code continues here, not getting the input value :/ */
try
{
threadx.Abort();
}
catch
{
}
return "";
}
public static string GetValueStringx()
{
WindowWrapper window = new WindowWrapper(Fun.GetForegroundWindow());
FormInput formlicencia = new FormLicencia();
formlicencia.ShowDialog(window);
Cons.inputvalue = formlicencia.inputvalue; //thread gets stuck here
/*even if i comment all the above lines and i put
directly Cons.inputvalue="valx"; it gets stuck too :s */
}
}
In the end I solved it using this response in this question. Is there some way to give credit to that user? If not i would give the anwser or upvotes to someone that can explain why the subthread gets stuck accesing the static variable...
How do I know the log the last property that is null?
For example,
var a = "somevalue";
......
......
if(a == null)
{
Log.Error(MethodBase.GetCurrentMethod().Name + "Property : a is null");
//blah blah
}
Like how I use the reflection to get the current method name, there should be some means by which I can log the latest local variables (or a property or fields)
that is being compared ? I use, log4net by the way to log the errors.
1) Is there any method to achieve this or should we manually log it?
2) Is there any custom method that prints the class -> MethodName -> Propertyname(or FieldName) that is null?
Thanks for your time in advance.
As mentioned by #fsimonazzi, "a" would be a local variable.
That being said there is still no way to examine the current compare operation as in MSIL there is no formal concept of an IF block - only conditional jumps.
If you wanted to get really crazy with the reflection, you may be able to find the current executing instruction and look around near that for a variable, but even then, you will not find the name - only a reference - as names are only used prior to compilation.
Either way, reflection is not going to help you here.
Instead, try using Exceptions - specifically ArgumentNullException. This body of code would become:
void doStuff(string param1, int param2)
{
if (param == null)
throw new ArgumentNullException("param1", "param1 must not be null");
if (param2 < 0)
throw new ArgumentOutOfRangeException("param2", "param2 should be non-negative.");
//method body
}
then, when you call the method, you can catch the exception and log it - no matter what it may be.
public static void Main(string[] args)
{
try
{
doStuff(null, 3);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
Tools like FxCop can help make sure that you are properly validating each parameter.
Properties are actually implemented as methods, so reflection could help you there. If, for example, you were validating in a property and wanted to log the position automatically, you could.
private object _cachedObject = null;
public object CachedObject
{
get
{
if (_cachedObject == null)
{
log(MethodBase.GetCurrentMethod().Name, "creating cached object");
_cachedObject = createCachedObject();
}
return _cachedObject;
}
}
The .Net Framework 4.5 also brings with it a new attribute that can be used to replace the MethodBase.GetCurrentMethod().Name construct you are using to get the method name. See [CallerMemberNameAttribute][3].
For my current 'testing the waters' project, I'm trying to not use any Try-Catch blocks but instead catch each error (other than fatal) in other ways.
Now, when I say catch errors, my very contrived program makes one error which is easy to avoid; It tries to divide by 0 and this can be prevented by an If statement. To keep it simple I have only 1 C# file, with 1 class and two methods. I guess this is like a template, where the Constructor starts a process:
public class myObject
{
public myObject()
{
Object objOne = methodOne();
methodThree(objOne);
}
public object methodOne()
{
//logic to create a return object
int x = 0;
//I've added a condition to ensure the maths is possible to avoid raising an exception when, for this example, it fails
if (x > 0)
int y = 5 / x;
return object;
}
public void procesObjects(Object objOne)
{
//logic
}
}
So, as you can see in methodOne() I've added the if statement to ensure it checks that the maths isn't dividing by 0. However, since I've caught it, my application continues which is not desired. I need a way to cease the application and log the failing for debugging.
So, this is what I think could work:
Create a class called Tracking which for this example, is very simple (or would a struct be better?).
public class Tracking
{
StringBuilder logMessage = new StringBuilder();
bool readonly hasFailed;
}
I can then update my code to:
public class myObject
{
Tracking tracking = new Tracking();
public myObject()
{
Object objOne = methodOne();
if (!tracking.hasFailed)
methodThree(objOne);
if (tracking.hasFailed)
ExteranlCallToLog(tracking);
}
public object methodOne()
{
//logic
int x = 0;
//I've added a condition to ensure the maths is possible to avoid raising an exception when, for this example, it fails
if (x > 0)
int y = 5 / x;
else
{
tracking.hasFailed = true;
tracking.logMessage.AppendLine("Cannot divide by 0");
}
//may also need to check that the object is OK to return
return object;
}
public void procesObjects(Object objOne)
{
//logic
}
}
So, I hope you can see what I'm trying to achieve but I have 3 questions.
Should my tracking object (as it is in this example) be a class or a struct?
I'm concerned my code is going to become very noisy. I'm wondering if when the system fails, it raises an event within the Tracking object which logs and then somehow closes the program would be better?
Any other ideas are very welcome.
Again, I appreciate it may be simpler and easier to use Try-Catch blocks but I'm purposely trying to avoid them for my own education.
EDIT
The reason for the above was due to reading this blog: Vexing exceptions - Fabulous Adventures In Coding - Site Home - MSDN Blogs
Seriously, Dave - try catch blocks are there for a reason. Use them.
Reading between the lines, it looks like you want to track custom information when something goes wrong. Have you considered extending System.Exception to create your own bespoke implementation suited to your needs?
Something along the lines of:-
public class TrackingException : System.Exception
{
// put custom properties here.
}
That way, when you detect that something has gone wrong, you can still use try/catch handling, but throw an exception that contains pertinent information for your needs.
The following code works fine until I upgrade to .NET 4 (x64)
namespace CrashME
{
class Program
{
private static volatile bool testCrash = false;
private static void Crash()
{
try
{
}
finally
{
HttpRuntime.Cache.Insert("xxx", testCrash);
}
}
static void Main(string[] args)
{
Crash();
// Works on .NET 3.5 , crash on .NET 4
}
}
}
Did I just uncover a runtime bug, or is there some issue with my usage?
This would appear to be a bug in the CLR - you should report it to Microsoft.
Note that the StackOverflowException occurs as the CLR attempts to execute the Crash, not during the execution of the Crash method - the program in fact never enters the method. This would appear to indicate that this is some low-level failure in the CLR. (Also note that the thrown exception also has no stack trace).
This exception is incredibly specific to this situation - changing any one of a number of things fixes this, for example the following code works fine:
private static void Crash()
{
bool testCrash2 = testCrash;
try { }
finally
{
HttpRuntime.Cache.Insert("xxx", testCrash2);
}
}
I would recommend that you report this to Microsoft, but attempt to work around the issue by tweaking your code in the meantime.
I can reproduce it on an x86 machine. The following code also fails:
try
{
}
finally
{
var foo = new List<object>();
foo.Add(testCrash);
}
However, the following code succeeds:
try
{
}
finally
{
var foo = new List<bool>();
foo.Add(testCrash);
}
I thought it might have something to do with the boxing of volatile fields within the finally block, but then I tried the following (which also fails):
try
{
}
finally
{
bool[] foo = new bool[1];
foo[0] = testCrash;
}
Very interesting problem...
I was writing some try-catch blocks for various methods today, and thought to myself it would be good to have utility method which would automatically call the method again for a number of times specified in a parameter, at a certain time.
However, I thought to myself, the method/property etc which will cause an exception will be at the top of the stacktrace (do property calls get put on the stacktrace?) in a single threaded application (so an application with no code relating to threading). So I can simply get the method name at the top and dynamically call it again.
So I would have code like:
string s = StackTrace.GetFrame(0).GetMethodName; (I can't remember the exact syntax).
With this method, I can execute it using an activator or one of several other ways.
But in a multi-threaded application, I could have several methods firing at once and I wouldn't know which one finishes first/last. So I can't expect a method for which I write a try-catch block to be at the top of the stack.
How would I go about achieving this?
Please don't do this. It's a really, really, really, really, really bad idea.
Maybe not as bad as deleting files randomly, if the hard drive runs out of room - but just about as bad.
While I question the need for an auto retrying mechanism (does randomly retrying really help you out in so many situations that you need a utility method?) - using StackTrace and Reflection is, at best, a terribly complicated solution.
Not that I suggest that anyone actually use this code, but I'd probably go with a delegate based approach to this particular problem:
public static class Extensions {
public static void Try(this Action a, int maxTries) {
new (Func<bool>(() => { a(); return true; })).Try(maxTries);
}
public static TResult Try<TResult>(this Func<TResult> f, int maxTries) {
Exception lastException = null;
for (int i = 0; i < maxTries; i++) {
try {
return f();
} catch (Exception ex) {
lastException = ex;
}
}
throw lastException;
}
}
Usage is a bit unorthodox, but fairly clear I think:
// Set a property
new Action(() => myObject.Property = 5).Try(5);
// With a return value
var count = new Func<int>(() => myList.Count).Try(3);
You can't inline a lambda to a method, but you could have a somewhat fluent interface:
Utilities.Try(
() => MyObject.Property = 5
).Repeat(5);
And multi line methods:
Utilities.Try(() => {
MyObject.Property1 = 5;
MyObject.Property2 = 6;
MyObject.Property3 = 7;
}).Repeat(5);
Mark's code is probably better, but here's mine...
If you really want to do something like this, I'd use code something like this. Yes, you still have to manually call it, but your idea of indiscriminately retrying ALL excepting methods is a really, really bad idea.
public class TryAgain
{
public delegate void CodeToTryAgain ();
public static void Repeat<E>(int count, CodeToTryAgain code) where E : Exception
{
while (count-- > 0)
{
try
{
code();
return;
}
catch (E ex)
{
Console.WriteLine("Caught an {0} : {1}", typeof(E).Name, ex.Message);
// ignoring it!
}
}
}
}
And then you'd call your failing method, ThrowTwice, or whatever you want to do, like this:
TryAgain.Repeat<MyException>(5, delegate()
{
ThrowTwice();
});
In this example, the Repeat method will ignore all exceptions of type MyException, trying to call ThrowTwice up to 5 times...
You can add your own sleeping and time-outs, and whatever.