This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 2 years ago.
I'm trying to open a form from another form. This results in an ArgumentOutOfRangeException.
I think the error is here because I added this lists and my program stopped working:
private static List<string> proxies = ps.proxies;
private static int proxyCounter = 1;
private static string currentProxy = proxies[proxyCounter];
public int TokenTimes = 0;
the lists go to:
class proScanner
{
public List<string> proxies = new List<string>();
public void ScanProxies()
{
var fileText = File.ReadAllLines(#"settings\proxies.txt");
foreach (var s in fileText) proxies.Add(s);
}
}
Debugging can really help you track down your problem, view the values, and solve the problem.
I would guess that your problem is here:
proxyCounter = 1;
currentProxy = proxies[proxyCounter];
And the proxies has less than 2 values (Index starts at zero!).
But some of the reasons why you are having problems tracking down the errors is because you are doing many assignments in the class declaration
private static List<string> proxies = ps.proxies;
private static int proxyCounter = 1;
private static string currentProxy = proxies[proxyCounter];
You should only declare variables and set default values on the class level. Not assign them values from other variables, this should be done inside your class, inside the constructor for example.
You should also look to see if you really need to define all of these statically. I would suggest that you consider a different method.
Related
This question already has answers here:
Print out object elements from list [duplicate]
(2 answers)
Print List of objects to Console
(3 answers)
print list<object> in console c# [duplicate]
(2 answers)
Closed 2 years ago.
I'm learning to code. I have started a little project where I design a text-based RPG.
I am struggling with storing and retrieving objects in and from an array.
Please have a look at my progress so far and tell me what I am doing wrong.
If I am using a wrong approach please also let me know how to do the whole thing smarter :)
First I define some properties of the player:
static class Globals
{
public static string playername;
...
public static object[] playerInventory = new object[4];
}
Then I create the weapon class:
public class Weapon
{
public string weaponName;
public int weaponBaseDamage;
public Weapon(string name, int baseDamage)
{
weaponName = name;
weaponBaseDamage = baseDamage;
}
Then I create the first basic weapon and try to store it in an array.
public class Program
{
public static void Main()
{
Weapon StartSword = new Weapon("My first Sword", 1);
Globals.playerInventory[0] = StartSword;
Console.WriteLine(StartSword.weaponName); // This works
Console.WriteLine(Globals.playerInventory[0]); // This prints "CSharp_Shell.Weapon", but I expected "StartSword"
Console.WriteLine(Globals.playerInventory[0].weaponName); // This results in an Error
The unexpected result of the second WriteLine command tells me that something must be quite wrong, but I don't know what it is and how to fix it. Any advice is welcome! (And please keep in mind that I am new to Coding).
It's required Typecasting. Please try like below:
Console.WriteLine(((Weapon)Globals.playerInventory[0]).weaponName)
Ok, lets look at what your code does:
Weapon StartSword = new Weapon("My first Sword", 1);
Globals.playerInventory[0] = StartSword;
Console.WriteLine(StartSword.weaponName); // This works
Above you create an object of the type Weapon with the name "My first Sword". And then print the name of that public property that is populated in the constructor.
Console.WriteLine(Globals.playerInventory[0]); // This prints "CSharp_Shell.Weapon", but I expected "StartSword"
Here you try to write an object. But an object is not a string so c# will automatically try to convert that to a string and will look at the type. So it is expected that it will not write the properties but a representation of the type.
Console.WriteLine(Globals.playerInventory[0].weaponName); // This results in an Error
Globals.playerInventory is defined as object[] playerInventory, so even if we know that you have entered an object of type weapon there, we need to specify that. Either by letting playerInventory be of the type Weapon[] playerInventory, or by type casting your object before using its properties, like this:
Console.WriteLine(((Weapon)Globals.playerInventory[0]).weaponName);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm new to C# and having trouble understanding the scope of variables. I've declared an array at the beginning of the class:
namespace TextProcessing
{
public static class Program
{
private static string[] ForewordArray;
Then in Main, I initialize and fill the array:
public static void Main(string[] args)
{
try
{
try
{
//snip - XML source is opened - snip
foreword = XMLnav.SelectSingleNode("//iso:foreword", NSmgr);
forewordText = foreword.InnerXml;
ForewordTextP = (forewordText.Length - forewordText.Replace("<p", string.Empty).Length) / 2 + 1;
CurrFPos = 1;
LastFPos = 1;
string[] ForewordArray = new string[ForewordTextP];
for (var z = 0; z <= ForewordTextP - 1; z++)
{
LastFPos = CurrFPos;
if (z < ForewordTextP - 1)
{
CurrFPos = Strings.InStr(LastFPos, forewordText, "<p");
if (LastFPos > 1)
{
ForewordArray[z] = Strings.Left(Strings.Mid(forewordText, LastFPos - 1), CurrFPos - LastFPos - 1);
}
else
{
ForewordArray[z] = Strings.Left(Strings.Mid(forewordText, LastFPos), CurrFPos - LastFPos - 1);
}
CurrFPos = CurrFPos + 1;
}
else
{
CurrFPos = Strings.InStr(LastFPos, forewordText, "p>");
ForewordArray[z] = Strings.Left(Strings.Mid(forewordText, LastFPos-1), CurrFPos - LastFPos + 3);
}
}
}
After some other text processing, when execution returns to the array (still in Main!), it's null:
foreach (var bkmkStart in wordDoc.MainDocumentPart.RootElement.Descendants<BookmarkStart>())
{
if (bkmkStart.Name == "ForewordText")
{
forewordbkmkParent = bkmkStart.Parent;
for (var y = 0; y <= ForewordArray.Length - 1; y++)
{
var TextProcessP = new Para2XML(ForewordArray[y]);
forewordbkmkParent.InsertBeforeSelf(TextProcessP.PReturn);
}
}
}
Is this happening because I initialize the array inside a Try loop?
I've read dozens of pages about variable scope in C# and I'm still not getting it. Thanks for any reading suggestions.
You are declaring a new local array inside Main and this is getting initialized with data. It looks like the second block of code is then accessing the class level array, which was never initialized.
In Main, the following line is declaring a new string array called ForewordArray because you start this line with the type.
string[] ForewordArray = new string[ForewordTextP];
In order to initialize the array you declared up at the top of the class, this should be as follows:
ForewordArray = new string[ForewordTextP];
Scope is actually pretty simple. If a class contains a variable, anything within that class sees it. However, anything outside that class/block cannot access that variable.
It's like a hierarchy of dropdowns. Click on a dropdown, and you see everything it contains. If it contains other dropdowns, click on those, and you see what they contain. Each dropdown only knows about the stuff it contains. This means that the dropdown which contains everything (or, in other words, within which everything is nested) can see everything.
There is a complication when variables are named the same way. If one class contains a variable, and a class within it contains another variable with the same name, the class inside will override the variable's name, because it is more precise in context.
Writing string[] ForewordArray = new ... declares a new array variable. So the containing class Program's ForewordArray is getting overridden by the child class' ForewordArray. The notation string[] creates a new variable of type string array. To initialize the variable instead, just use the variable name ForewordArray.
This question already has answers here:
In C#, why can't I modify the member of a value type instance in a foreach loop?
(8 answers)
Closed 3 years ago.
Please consider the following code:
public class Program {
public struct A
{
public int Prop {get;set;}
}
public static void Main()
{
var obj = new A();
obj.Prop = 10;
var list = new List<A>(){obj};
foreach(var l in list) {
l.Prop = 20; //here I'm getting compile time error "Cannot modify members of 'l' because it is a 'foreach iteration variable'"
}
}
}
So my question is: why struct properties cannot be assigned while iterating over a list of structs?
Please note that even when iterating with simple for like this:
for (int i=0; i<list.Count(); ++i)
list[i].Prop = 20;
I'm still getting compile time error...
You cannot modify collection over which you are iterating with foreach.
Instead you should use for loop, which allows that:
for(int i = 0; i < list.Length; i++)
{
list[i].Prop = 200;
}
You can refer to this question: Why can't we assign a foreach iteration variable, whereas we can completely modify it with an accessor?
This question already has answers here:
Access private fields
(4 answers)
Closed 6 years ago.
I recently had an interview with C# questions. One of them I cannot find an answer to.
I was given a class, looks like this:
public class Stick
{
private int m_iLength;
public int Length
{
get
{
return m_iLength;
}
set
{
if (value > 0)
{
m_iLength = value;
}
}
}
}
Also, a main class was given
static void Main(string[] args)
{
Stick stick = new Stick();
}
The task was to add code to the main that will cause m_iLength in the Stick class to be negative (and it was stressed out that it can be done).
I seem to miss something. The data member is private, and as far as I know the get and set function are by value for type int, so I do not see how this can be done.
Reflection is always the most direct:
var type = typeof(Stick);
var field = type.GetField("m_iLength", BindingFlags.NonPublic |BindingFlags.GetField | BindingFlags.Instance);
field.SetValue(stick, -1);
Console.WriteLine(stick.Length);
Explanation:
The first line gets the Type object for Stick, so we can get the private fields later on.
The second line gets the field that we want to set by its name. Note that the binding flags are required or field will be null.
And the third line gives the field a negative value.
my problem is as follows:
Im building a console application which asks the user for the numbers of objects it should create and 4 variables that have to be assigned for every object.
The new objects name should contain a counting number starting from 1.
How would you solve this?
Im thinking about a class but im unsure about how to create the objects in runtime from userinput. Is a loop the best way to go?
What kind of class, struct, list, array .... would you recommend. The variables in the object are always the same type but i need to name them properly so I can effectivly write methods to perform operations on them in a later phase of the program.
Im just learning the language and I would be very thankful for a advice on how to approach my problem.
If I understand your problem correctly:
class MyClass
{
public int ObjectNumber { get; set; }
public string SomeVariable { get; set; }
public string AnotherVariable { get; set; }
}
// You should use keyboard input value for this
int objectsToCreate = 10;
// Create an array to hold all your objects
MyClass[] myObjects = new MyClass[objectsToCreate];
for (int i = 0; i < objectsToCreate; i++)
{
// Instantiate a new object, set it's number and
// some other properties
myObjects[i] = new MyClass()
{
ObjectNumber = i + 1,
SomeVariable = "SomeValue",
AnotherVariable = "AnotherValue"
};
}
This doesn't quite do what you described. Add in keyboard input and stuff :) Most of this code needs to be in some kind of Main method to actually run, etc.
In this case, I've chosen a class to hold your 4 variables. I have only implemented 3 though, and I've implemented them as properties, rather than fields. I'm not sure this is necessary for your assignment, but it is generally a good habit to not have publically accessible fields, and I don't want to be the one to teach you bad habits. See auto-implemented properties.
You mentioned a struct, which would be an option as well, depending on what you want to store in it. Generally though, a class would be a safer bet.
A loop would indeed be the way to go to initialize your objects. In this case, a for loop is most practical. It starts counting at 0, because we're putting the objects in an array, and array indexes in C# always start at 0. This means you have to use i + 1 to assign to the object number, or the objects would be numbered 0 - 9, just like their indexes in the array.
I'm initializing the objects using object initializer syntax, which is new in C# 3.0.
The old fashioned way would be to assign them one by one:
myObjects[i] = new MyClass();
myObjects[i].ObjectNumber = i + 1;
myObjects[i].SomeVariable = "SomeValue";
Alternatively, you could define a constructor for MyClass that takes 3 parameters.
One last thing: some people here posted answers which use a generic List (List<MyClass>) instead of an array. This will work fine, but in my example I chose to use the most basic form you could use. A List does not have a fixed size, unlike an array (notice how I initialized the array). Lists are great if you want to add more items later, or if you have no idea beforehand how many items you will need to store. However, in this case, we have the keyboard input, so we know exactly how many items we'll have. Thus: array. It will implicitly tell whoever is reading your code, that you do not intend to add more items later.
I hope this answered some questions, and raised some new ones. See just how deep the rabbit hole goes :P
Use a list or an array. List example:
int numberOfObjects = 3;
List<YourType> listOfObjects = new List<YourType>();
for(int i = 0 ; i < numberOfObjects ; i++ )
{
// Get input and create object ....
// Then add to your list
listOfObjects.Add(element);
}
Here, listOfObjects is a Generic list that can contain a variable number of objects of the type YourType. The list will automatically resize so it can hold the number of objects you add to it. Hope this helps.
If I understood what you are asking you could probably do something like this:
class Foo
{
private static int count;
public string name;
public Foo(...){
name = ++count + "";
}
}
I'm guessing what you're trying to do here, but this is a stab in the dark. The problem I'm having is dealing with the whole "the new objects name should contain a counting number starting from 1" thing. Anyway, here's my attempt:
public class UserInstantiatedClass
{
public int UserSetField1;
public int UserSetField2;
public int UserSetField3;
public int UserSetField4;
public string UserSpecifiedClassName;
}
public static class MyProgram
{
public static void Main(string [] args)
{
// gather user input, place into variables named
// numInstances, className, field1, field2, field3, field4
List<UserInstantiatedClass> instances = new List< UserInstantiatedClass>();
UserInstantiatedClass current = null;
for(int i=1; i<=numInstances; i++)
{
current = new UserInstantiatedClass();
current.UserSpecifiedClassName = className + i.ToString(); // adds the number 1, 2, 3, etc. to the class name specified
current.UserSetField1 = field1;
current.UserSetField2 = field2;
current.UserSetField3 = field3;
current.UserSetField4 = field4;
instances.Add(current);
}
// after this loop, the instances list contains the number of instances of the class UserInstantiatedClass specified by the numInstances variable.
}
}