Cannot use local variable before it is declared - c#

I am trying to create a function but I'm getting an error message.
public int[] genericSearch(int searchWidth, int startingRadius, int width, int height, Bitmap bitmap)
{
//Generic function for finding the best path from a certain range
if (startingRadius == -1)
startingRadius = bitmap.Height() / 2;
Cannot use local variable 'startingRadius' before it is declared.
The same problem occurs for the bitmap variable as well. Normally in c++ this type of declaration would work; however, I am unsure why it is not working here.

In visual studio. Sometimes when you declare a variable again (a second time). It will give this error. For example, this will sometimes throw the exception you mentioned:
1. int startingRadius = 0;
2. startingRadius = 5; <-- Exception thrown here.
3.
4. int startingRadius = 0;
Obviously this is incorrect anyway. So removing the second declaration (on line 4) will solve the problem.
Note: The exception you would ordinarily expect would be A local variable named 'startingRadius' is already defined in this scope. But for some reason, the exception you mentioned is shown sometimes.

You are missing a closing brace for your method but otherwise this code can compile on my machine... (changed Height to a property as well)
public int[] genericSearch(int searchWidth, int startingRadius, int width, int height,Bitmap bitmap)
{
//Generic function for finding the best path from a certain range
if (startingRadius == -1)
startingRadius = bitmap.Height / 2;
}

It sounds like you have a misplaced } or misspelled variable names. I can't really tell without seeing the full code.
The error message is basically telling you that you have a local variable that you are trying to use which has not been declared. Which suggests that the if (startingRadius == 1) code is actually inside a different method than the method you have declared.

For me it helped to delete to local variable at all and create a new with different name...
Originally:
string butterfly;
butterfly = "butterfly with error"; <-- gives error
UPDTE:
Delete all the existing "butterfly"s and create new with new very similar name
string butterfly2;
butterfly2 = "butterfly without error" <-- worked for me perfectly.
*First tried:
clean and rebuild project - didn't help
restart whole program(IDE) - didn't help*

Change the variable name for example "butterfly" to "Butterfly" and declare it
under public partial class Form1 : Form
{
This is exactly where you have to declare it. It will then have scope for the entire class.
It worked for me.

Related

How struct variables are stored in C#

I Read this StackOverflow Question
And i read this blog here
I couldn't understand completely.
Here are my doubts.
struct S
{
private int x;
private int y;
public int X { get { return x; } }
public int Y { get { return y; } }
public S(int x, int y, bool panic)
{
this.x = x;
this.y = y;
if (panic)
throw new Exception();
}
}
static class P
{
static void Main()
{
S s = default(S);
try
{
s = new S(1, 2, false);
Console.WriteLine("{0}, {1}", s.X, s.Y);
s = new S(3, 4, true);
}
catch
{
Console.WriteLine("{0}, {1}", s.X, s.Y);
}
Console.ReadLine();
}
}
Here before throwing exception i assigned the values. But why is it not assigning to the object s i mean in the console i written in the catch block,
says (1,2).
Because it is initialized again in the second line , and called the constructor with (3,4). so how it is (1,2).
Somehow i cant understand this.
And also,
Therefore, using the new operator on a value type allocates no additional memory. Rather, the memory already allocated for the value is used.
In that blog , the answer is No.
If that is the case, is it initializing with new memory. If so, how comes (1,2) is coming in the catch block.
As i am new to C# i am not able understand this.
I know its silly doubt, but someone please help me in understanding this concept.
Quoted from the blog Debunking another myth about value types:
The C# specification is clear on this point:
"If T is a struct type, an instance of T is created by allocating a temporary local variable"
That is, the statement
s = new S(123, 456);
actually means:
Determine the location referred to by s.
Allocate a temporary variable t of type S, initialized to its default value.
Run the constructor, passing a reference to t for "this".
Make a by-value copy of t to s.
You are throwing the exception during the third stage:
Run the constructor, passing a reference to t for "this"
Meaning the last stage, which copies to s never occurs, hence you see the current values of s which in your case is 1, 2.
Because it is initialized again in the second line , and called the constructor with (3,4).
You've called the constructor, but the constructor itself hasn't finished - so the assignment to s never takes place.
This of this:
s = new S(3, 4, true);
As equivalent to :
// Create the new value
S tmp = new S(3, 4, true);
// Copy it into the s variable
s = tmp;
The first statement never completes, so the assignment doesn't occur... so you still see the first value of s in the catch block.
In the console you print s.X and s.Y. This is the first s from
s = new S(1, 2, false);
the second assignment is never executed, because the Exception is thrown.
The Exception is Happening before the assignment to the S on the left side of the equals sign.
So your catch block writes out the original values from the previous assignment.
The Capital S variable is a Type and the small s is an instance.
Struct constructors are implemented as methods which take the structure being constructed as an implied ref parameter. In many cases, a compiler will implement a statement like:
s = new StructType(4);
as equivalent to
var temp = default(StructType);
StructType..ctor(out temp, 4); // Not possible with C# syntax
s = temp;
There are, however, some cases where it does not do so, but instead simply does:
StructType..ctor(out s, 4);
and where this may be observable, especially when interacting with code written in other languages which do not honor the attribute C# uses to mark out parameters.
For example, although it is not possible to write an implementation of IDictionary.TryGetValue in C# which won't store a default(TValue) to its out parameter, that parameter will be see by other languages as a ref parameter; consequently, an implementation written in another language may return without writing anything to it. If a struct constructor passes this to the TryGetValue method of a passed-in IDictionary but doesn't do anything else, the actual behavior of struct construction may be observed.

An object reference is required for the non-static field error

I have a long method that ends up returning a DataTable. The method opens like this:
public DataTable ImportCsvData(string folderPath, string[] csvFileNames, int compIdValue)
{
int countDupFiles = 0;// Count number of previously imported csv files
int countImportedFiles = 0;// Count imported files
for (int i = 0; i < csvFileNames.Length; i++)
{
frmImportCsvData.importProgressBar(i);
This method is inside a class where I am doing all of my SQL requests but is called from another class that controls my Form. The last line of code above calls a method back in my Form class which should update my progress bar. The code for that method is:
public void importProgressBar(int i)
{
progressTableLayoutPanel.Visible = true;//display progress bar
int percProgress = 100 * (i + 1) / csvFileNames.Length;
while (percProgress < 100)
{
if (percProgress <= 99)// Required to prevent values above 100 that crash the code
progressBar.Value = percProgress + 1;//hack that makes the progress bar update when progress value decreases
progressBar.Value = percProgress;
percProgressLabel.Text = percProgress.ToString();
progressTableLayoutPanel.Update();//Required to display all progress bar table contents
//Thread.Sleep(200);
}
progressTableLayoutPanel.Visible = false;
}
This gives me the error: An object reference is required for the non-static field, method, or property 'BetfairDatabaseMDI.frmImportCsvData.importProgressBar(int)'. If I set the importProgressBar method to static I get a bunch of other similar errors. Could anybody advise me how to fix this please?
frmImportCsvData is a class, so a type, which is an abstract thing, not a real object in memory. The error message says you need an instance of a type, so a concrete, existing thing, an object in memory of that given type.
So, essentially, you need to pass the instance of frmImportCsvData into ImportCsvData. For example, like this:
public DataTable ImportCsvData(frmImportCsvData myForm, …)
{
myForm.importProgressBar(i);
}
Then to call the method from within frmImportCsvData you just pass in this, which denotes the current instance (in run-time sense) of the enclosing class:
dataLayer.ImportCsvData(this, …);
Simplest doesn't mean best or correct in respect to the particular UI framework you are using (being it WinForms, WPF, whatever). BUT: You definitelly have to understand the differences between a type and an instance of a type first, before you run into any more complex constructs. So grab a C# book and get back to the basics, that will help you the most.
Note: It is a common convention to start identifiers of methods, classes and properties with an upper-case letter.

On Scope of Variables in .NET(c#) [duplicate]

This question already has answers here:
Variable scope confusion in C#
(4 answers)
Closed 9 years ago.
Reference Code
public void MyMethod()
{
string x;
List sampleList = populateList();
foreach(MyType myType in sampleList)
{
string x; // why is this not allowed?
doSomethingwithX(x);
}
}
I recently started learning C# and today ran into issue with code similar to the above. VS2010 flagged the commented code with this message a local variable named x cannot be declared in this scope because it would give a different meaning to variable x which is already used in parent or current scope to denote something else....
I dont get it...isnt that the whole essence of block statements and scoping...I know i can just change my variable names and go ahead.but i'd like to know WHY?
I dont get it...isnt that the whole essence of block statements and scoping...
No, not really. The intention of scoping isn't "to allow you to reuse names".
I know i can just change my variable names and go ahead.but i'd like to know WHY?
It reduces the possibilities for confusing code, basically. There are various situations where C# prevents you from writing code which is confusing. Not as many as we might like, of course, but where there's no clear benefit from allowing something, and a clear benefit from disallowing it, it makes sense to disallow it.
Would you ever want to work with code that had the same local variable name in scope twice? Wouldn't you always prefer the original developer to use a different name? I would - so I'm glad the compiler enforces that.
Note that this doesn't prevent the same local variable name being used twice in the same method - they just can't be in the same scope. So this is valid:
public void Foo()
{
{
int x = 10;
...
}
{
int x = 10;
...
}
}
But this isn't:
public void Foo()
{
{
int x = 10;
...
}
int x = 10;
...
}
If the second example is confusing, you need to bear in mind that the scope of a local variable is the block in which it was declared - not from the declaration point onwards.
Previously defined x is still in scope that's why compiler stops you from declaring other one.
You can verify this by limiting the scope of previous variable by wrapping it in curly braces -
public void MyMethod()
{
{
string x;
}
List sampleList = populateList();
foreach(MyType myType in sampleList)
{
string x; // This will be fine.
doSomethingwithX(x);
}
}
The x in the for loop is not visible outwith the loop, but the x you declared at the start of the method is visible within the for loop.
Outwith the loop you have one x but inside it there are two, both of which are being declared
You cannot declare string x; again. .. it will have different meaning. Since string x; is declared inside a method. The scope of x will be available through out the method. . So please declare some other variable inside for each loop. ..
Or you can just x. Instead of declaring again. .

Referring to an object defined by a variable

I have a problem, which I couldn't solve recently.
I have this code
foreach (Hashtable i in (ArrayList)inv["database"])
{
if (i != null)
{
if (i["type"].ToString() == "1")
{
if (i["dataValue"].ToString() != "0")
{
inv{nn}.Image = Program.Properties.Resources._i["type"].ToString()+"-"+i["dataValue"].ToString();
}
else
{
inv{nn}.Image = Program.Properties.Resources._i["type"].ToString()
}
}
}
nn++;
}
I have 36 controls(it's a class i have in my project, so not "vanilla" one), and each one of them is a single "picturebox". I have 505 images in the following syntax:
If the data value is 0, then it's {typeID}.png, if the data value is above 0, then {typeID}-{dataValue}.png
So for example if it's the first loop, i["type"].ToString() = 1 and i["dataValue"].ToString() = 3, the Image of inv0 changes to Program.Proporties.Resources._1-3
When the second loop comes the image of inv1 changes etc. ... till inv35
Is such thing possible? I tried
InterpolationBox x = Form1.FindControl("inv"+nn)
and I seem not to have such thing as FindControl (FrameWork 4) with System.Web.UI used.
I tried
InterpolationBox x = this.Controls.Find("inv" + nn, false);
And I got Unable to cast object of type 'System.Windows.Forms.Control[]' to type 'Program.InterpolatedBox'. And anyway, if I'd get rid of that error, would I be able to change that actual picturebox, not just the copied 'x' one?
InterpolationBox x = this.Controls.Find("inv" + nn, false);
Is where your problem lies.
The error you got is telling:
Unable to cast object of type 'System.Windows.Forms.Control[]' to type
'Program.InterpolatedBox'.
You can see it's saying it can't cast an array of System.Windows.Forms.Control to a Program.InterpolationBox which is sensible given InterpolationBox is a single control.
The Find method returns an array of controls, not just one, so you need to then look in the array and pull out the one you're after (even if it's just the first one).
As for your question about whether changing x would change the control you got given using Controls.Find() the answer is YES.
Objects in .NET are by reference, which means x isn't an InterpolationBox it's a reference to an InterpolationBox in memory.
You could even do:
var a = x;
var b = a;
var c = b;
c.DoSomething();
The code you call against c will operate against the same object, they're all just references pointing to the same thing.

Mono + named/optional parameters = compiler bug?

I have encountered some unforeseen consequences of porting to mono 2.8.1. Problem can be boiled down to a sample program (I have been unable to reduce it further, after cutting several classes and ~1000 lines of code to the file quoted below)
public class Person
{
public Person(int age, string name = null){}
public Person(double income, string name = null){}
public Person(double income, int age, string name = null){}
}
class Program
{
static void Main()
{
Person p = new Person(1.0, name: "John Doe");
}
}
Compilation of above code with mcs gives output:
test.cs(22,24): error CS0584: Internal compiler error: Internal error
test.cs(22,20): error CS0266: Cannot implicitly convert type `object' to `NamedParams.Person'.
An explicit conversion exists (are you missing a cast?)
Compilation failed: 2 error(s), 0 warnings
Removing use of optional/named parameter (i.e. calling new Person(1.0, null, "John Doe") or new Person(1.0, null, name:"John Doe"), or new Person(1.0, "John Doe") ) leads to flawless compilation. Also, under VS2010 the file (and whole solution with which I started with) compiles fine. Casting removes error CS0266, but not CS0584 -- so no surprise there.
My question: is it me doing something wrong, or mcs (i.e. bug in mcs is obvious to me -- what else ,,internal error'' would mean, but perhaps it's ok such program won't compile), or maybe Microsoft compiler in VS2010 should not let such code to compile?
I bet it's mcs who's wrong (unable to guess right constructor), but perhaps it's otherwise and I shouldn't know better?
PS. I tried searching for a known bug like this in both Google and Novell's Bugzilla, but was unable to find anything relevant. Again, I may be blind ;)
Okay, here goes. The crash is indeed due to the third overload, Person(double income, int age, string name = null).
The compiler sees you are trying to pass less arguments than what are listed in the signature so it goes looking for optional arguments. It happily notices that name is optional and assumes you are not passing that argument. It does this by appending a placeholder at the end of the supplied arguments. Next, it goes to reorder the named arguments in the list so they end up in their right position. This means John Doe is now correctly at the last position for name, but the placeholder gets into the age position. The compiler then tries to fill in the default values, but is shocked to find a placeholder at a location which has no default value. It thinks this can not happen, since the placeholder was only added for an optional argument and now suddenly it is not optional anymore. Not knowing what to do, it throws an exception.
The following patch seems to fix the issue (however it may break something else, so no warranty):
--- mono-2.6.7.orig/mcs/mcs/ecore.cs 2009-10-02 12:51:12.000000000 +0200
+++ mono-2.6.7/mcs/mcs/ecore.cs 2010-12-21 02:26:44.000000000 +0100
## -3803,6 +3803,15 ##
int args_gap = Math.Abs (arg_count - param_count);
if (optional_count != 0) {
+ // readjust for optional arguments passed as named arguments
+ for (int i = 0; i < arguments.Count; i++) {
+ NamedArgument na = arguments[i] as NamedArgument;
+ if (na == null)
+ continue;
+ int index = pd.GetParameterIndexByName (na.Name.Value);
+ if (pd.FixedParameters[index].HasDefaultValue)
+ optional_count--;
+ }
if (args_gap > optional_count)
return int.MaxValue - 10000 + args_gap - optional_count;
For others coming to this thread. The bug is still there in the latest versions of Mono Compiler as of April 2013. I created a work around without needing to modify the compiler using C# overloaded functions.
Foo(int a, bool b = true) {
Foo(a, b, "Default String");
}
Foo(int a, bool b, string c)

Categories