I have an array in C#:
string[] foo = new string[11];
The length of foo array has been 10, I only changed it to 11 because I needed an extra value. My only problem is: I can't seem to change the length of the array. If I change it to 11, like in the above example, set a break point and debug, after the compiler passes this line, it still has a length of 10.
Now when I add a watch foo = new string[11] after the compiler passes this line, all the values are erased and the length is changed to 11. Basically I have no idea what is going on, especially why adding a watch has an effect on the runtime values of variables.
Does anybody have any idea what is happening here?
public string[] getValues()
{
//Why does this only have 10 dimensions after initialization?????
string[] values = new string[11];
string[] temp = ddlProjectnumber.Text.Split('-'); //<----- here I set break point.
values[0] = temp[0].Trim();
values[1] = tbTask.Text;
values[2] = ddlSubstitute.Text;
values[3] = ddlCategory.Text;
values[4] = ddlSubcategory.Text;
values[5] = cbFinished.Checked.ToString();
if (propertychanged)
{
values[6] = DateTime.Now.ToString();
}
values[7] = cbJourney.Checked.ToString();
return values;
}
Your code will be easier to maintain if you create a class to hold your values:
public class MyClass
{
public string ProjectNumber { get; set; }
public string Task { get; set; }
public string Substitute { get; set; }
public string Category { get; set; }
public string Subcategory { get; set; }
public bool Finished { get; set; }
public DateTime? PropChangedDate { get; set; }
public bool Journey { get; set; }
}
Then adjust your method to just populate an instance of the class and return that instead:
public MyClass GetValues()
{
var myClass = new MyClass
{
ProjectNumber = ddlProjectnumber.Text.Split('-').First().Trim(),
Task = tbTask.Text,
Substitute = ddlSubstitute.Text,
Category = ddlCategory.Text,
Subcategory = ddlSubcategory.Text,
Finished = cbFinished.Checked,
Journey = cbJourney.Checked
};
if (propertychanged)
myClass.PropChangedDate = DateTime.Now;
return myClass;
}
Now you don't have to guess which values were stored in each element of the array.
okay I played around a bit and after changing my configuration from debug to release and then to debug again, it apparently fixed itself. I guess it really was old code, but for some reason, it did not recompile correctly after I cleaned and rebuild my solution. anyway it works now :)
Related
I have a class that I am populating with a view to serializing into JSON
My class has strings and one IEnumerable of a second class (Icons)
public class ManifestModel
{
public string ShortName { get; set; }
public string Name { get; set; }
public IEnumerable<Icon> Icons { get; set; }
public string BackgroundColour { get; set; }
public string ThemeColour { get; set; }
public class Icon
{
public string Src { get; set; }
public string Type { get; set; }
public string Sizes { get; set; }
}
}
When creating an instance of ManifestModel, it is easy enough to populate the string properties, but how do I add my two icon variables (icon192 and icon512)?
var icon192 = new ManifestModel.Icon
{
Src = "192",
Type = "images/png",
Sizes = "192x192"
};
var icon512 = new ManifestModel.Icon
{
Src = "512",
Type = "images/png",
Sizes = "512x512"
};
var manifestModel = new ManifestModel
{
ShortName = siteRoot.GetValue<string>("siteTitle"),
Name = siteRoot.GetValue<string>("siteName"),
//how to add two Icon objects here
};
I have tried
Just create an array and assign to Icons property.
var manifestModel = new ManifestModel
{
Icons = new[] { icon192, icon512 },
//...
Because Icons is an IEnumerable, you can create a list
var manifestModel = new ManifestModel
{
Icons = new List<ManifestModel.Icon>() { icon192, icon512 },
//do something
It is uncommon to use a read/write property to maintain a list of items in an object. What you generally want is a solution, where you can just write:
foreach (Icon icon in model.Icons) {
//Do something
}
With a read/write property, Icons can be null and the result will be a NullReferenceException.
What is even worse is that you will add the potential for subtle bugs. When you start iterating over Icons and you set the value during the iteration, you might expect that you are continuing to iterate over the new list. This is not the case though, you're still iterating over the previous value. Usually in these cases the original iteration should fail with an InvalidOperationException upon continuation.
To avoid this problem, use a collection that is derived from System.Collections.ObjectModel.Collection<T> and expose it as a property:
public class IconCollection : Collection<Icon> {
//Customize here
}
public class ManifestModel
{
//
public IconCollection Icons { get; } = new IconCollection();
//...
}
When you want to add items you go:
model.Icons.Add(icon);
This will avoid the problems described above.
I need a clear example that shows me how to define a list that has n rows and 4 columns and how to use it. I need a list to save my data like the below image. as you see this could be a dictionary.
You need to create a class with all the above properties
public class Sample
{
public string vocabulary { get; set; }
public string meaning { get; set; }
public int number { get; set; }
public int group { get; set; }
}
and then you can create a List of type Sample,
List<Sample> yourList = new List<Sample>();
You can add items to the list as below
yourList.Add(new Sample { vocabulary = "massive", meaning = "very big", number = 5, group = 15 });
You can access them later like this, if you want the first element,
var result = yourList[0];
this is the easiest and best way of doing it. You need to create a new class and then create new instances of the class and then add it to the list and then use LINQ to get the data out
void Main()
{
var list = new List<myClass>()
list.Add(new myClass() {
Vocabluary = "Vocabluary ",
Meaning = "meaning",
Number = 1,
Group = 2})
}
public class myClass
{
public string Vocabluary { get; set; }
public string Meaning { get; set; }
public int Number { get; set; }
public int Group { get; set; }
}
yes... as Sajeetharan mentioned, with a custom class you can create an any dimensions List. but i don't think you need to think about dimension in C#... it is a bit more high level than that.
just simply create a class and put everything you need in it...
public class CustomClass{
public string d1;
public int d2;
public string d3;
public string d4;
...
//you can easily create a N dimension class
}
to access it and apply it
public void Main(){
List<CustomClass> list = new List<CustomClass>();
CustomClass cc = new CustomClass();
cc.d1 = "v1";
cc.d2 = 0; //v2
list.Add(cc);
//to access it
foreach(CustomClass tmpClass in list)
{
string d1Value = tmpClass.d1;
int d2Value = tmpClass.d2;
}
}
I wrote a parse class trying to handle parsing the data from a string array into it's appropriate value. I am trying to test this program to see if it will print out the value parse.open, and it is not. It is printing up 0's for the moment (which isn't accurate), until i could figure out why it's not showing what I need.
while (!r.EndOfStream)
{
ParseFileRead parse = new ParseFileRead();
string line = r.ReadLine();
//Send this to Parse class
string [] values = line.Split(',');
//parse records
Console.WriteLine(values[6]); //This is printing the accurate value for parse.open
ParseFileRead.Parse(values);
Console.WriteLine(parse.open); //This is not printing the accurate value
}
Console.Read();
vWriteFile.Close();
And here is my ParseFileRead class:
public class ParseFileRead
{
public int open { get; set; }
public int buy { get; set; }
public int sell { get; set; }
public double settleMM { get; set; }
public string account { get; set; }
public string underlying { get; set; }
public string symbol { get; set; }
public static void Parse(string[] arr)
{
ParseFileRead parse = new ParseFileRead();
parse.account = arr[0];
parse.underlying = arr[12];
parse.symbol = arr[1];
parse.open = Convert.ToInt32(arr[6]);
parse.buy = Convert.ToInt32(arr[7]);
parse.sell = Convert.ToInt32(arr[8]);
parse.settleMM = Convert.ToDouble(arr[10]);
}
}
This is actually correct.
The default value for an uninitialized int is 0.
You are creating a new instance of your ParseFileRead class which will have a value of 0 for open. You then check your parsed value to make sure it's reading in correctly using Console.WriteLine(values[6]);.
Next, you try to parse your values using the Parse function of your ParseFileRead class; which is a void function so it has no return value.
Inside your Parse function you have: ParseFileRead parse = new ParseFileRead(); which creates yet another new instance of your class with a value of 0 for open. This particular instance is never used anywhere and is not the same as the values of the properties created with your initial instance of ParseFileRead
If you put a Console.Write in your Parse function, I'm sure that you will see it being parsed correctly.
So you have 2 options:
Set the properties of your ParseFileRead inside the Parse class without creating a new instance of ParseFileRead
Return the newly created ParseFileRead instance out of your Parse function.
Or a 3rd Option, which is probably best as suggested by Plutonix:
/*Parse class*/
public class ParseFileRead
{
public int open { get; set; }
public int buy { get; set; }
public int sell { get; set; }
public double settleMM { get; set; }
public string account { get; set; }
public string underlying { get; set; }
public string symbol { get; set; }
public ParseFileRead(string[] arr)
{
this.account = arr[0];
this.underlying = arr[12];
this.symbol = arr[1];
this.open = Convert.ToInt32(arr[6]);
this.buy = Convert.ToInt32(arr[7]);
this.sell = Convert.ToInt32(arr[8]);
this.settleMM = Convert.ToDouble(arr[10]);
}
}
/*Parsing code*/
while (!r.EndOfStream)
{
string line = r.ReadLine();
//Send this to Parse class
string [] values = line.Split(',');
//parse records
Console.WriteLine(values[6]); //This is printing the accurate value for parse.open
ParseFileRead parse = new ParseFileRead(values);
Console.WriteLine(parse.open); //This is not printing the accurate value
}
I have a set of instance fields inherited from class G481Vars by object G481Var.
G481Vars G481Var = new G481Vars();
The values of the instance fields are assigned to through this function
private void AssignValuesG481()
{
HtmlInputText[] G481Inputs = new HtmlInputText[13] //Create an explicit array of type HtmlInputText to handle elements of input boxes on G481 tab.
{
G481Disp_Txt, G481IniVel_Txt, G481FinVel_Txt, G481Acc_Txt,
G481Time_Txt, G481Force_Txt, G481Mass_Txt, G481Weight_Txt,
G481Press_Txt, G481Dens_Txt, G481Energy_Txt, G481Area_Txt,
G481Vol_Txt
};
double[] G481List = new double[13] //Create an explicit array of type double that stores the instance fields of class G481Vars
{
G481Var.Disp, G481Var.IniVel, G481Var.FinVel, G481Var.Acc,
G481Var.Time, G481Var.Force, G481Var.Mass, G481Var.Weight,
G481Var.Press, G481Var.Dens, G481Var.Energy, G481Var.Area,
G481Var.Vol
};
for (int i = 0; i <= 12; i++) //Perform the iterative loop
{
if (G481Inputs[i].Value != "")
{
double.TryParse(G481Inputs[i].Value, out G481List[i]);
}
}
}
Where G481Vars is Defined as:
public class G481Vars
{
public double Disp { get; set; }
public double IniVel { get; set; }
public double FinVel { get; set; }
public double Acc { get; set; }
public double Time { get; set; }
public double Force { get; set; }
public double Mass { get; set; }
public double Weight { get; set; }
public double Press { get; set; }
public double Dens { get; set; }
public double Energy { get; set; }
public double Area { get; set; }
public double Vol { get; set; }
}
However when i try and access these instance fields from another function CalculateG481_Click They always return 0, even though they are assigned to before hand.
protected void CalculateG481_Click(object sender, EventArgs e)
{
AssignValuesG481();
TempInputDebugField.Value = Convert.ToString(G481Var.Disp); //This always returns 0 in the field, even though <>0 was put into the disp input field and assignvariables run.
}
When I put the TempInputDebugField code into the AssignValuesG481 function it returns the correct value. Any ideas on what is going on with the instance field?
Thanks for your help.
It seems like you think that setting the value of an element of G481List will forward that value on to the corresponding property of G481Var that was used to initialize the array. That is not true. all it does is change the values within the array.
You'll need to set the values of the instance explicitly. You could use reflection to set the properties dynamically, but with only 13 properties it would be much safer and cleaner to just set them explicitly:
G481Var.Disp = double.Parse(G481Inputs[0].Value)
G481Var.IniVel = double.Parse(G481Inputs[1].Value)
G481Var.FinVel = double.Parse(G481Inputs[2].Value)
G481Var.Acc = double.Parse(G481Inputs[3].Value)
G481Var.Time = double.Parse(G481Inputs[4].Value)
G481Var.Force = double.Parse(G481Inputs[5].Value)
G481Var.Mass = double.Parse(G481Inputs[7].Value)
G481Var.Weight = double.Parse(G481Inputs[8].Value)
G481Var.Press = double.Parse(G481Inputs[9].Value)
G481Var.Dens = double.Parse(G481Inputs[10].Value)
G481Var.Energy = double.Parse(G481Inputs[11].Value)
G481Var.Area = double.Parse(G481Inputs[12].Value)
G481Var.Vol = double.Parse(G481Inputs[13].Value)
From there you can use TryParse to better handle bad values, you can try using reflection to reduce duplicate code (at the expense of compile-time safety), etc. The point is to get something that works, then find ways to make it better. You can always go back to less "elegant" code if you get tired or stuck trying to refactor it.
Try this :
for (int i = 0; i <= 12; i++) //Perform the iterative loop
{
double val;
if (G481Inputs[i].Value != "")
{
double.TryParse(G481Inputs[i].Value, out val);
G481List[i] = val;
}
}
double is a valuetype, so when you parse the strings the values are stored only in the array. You will have to assign this values to G481Var properties:
double value;
if (double.TryParse(G481Disp_Txt.Value, out value)
G481Var.Disp = value;
Do this for each property and should works fine
I've seen a couple questions about this, and done some research.
My understanding is that when you run a foreach on IEnumerable: if T is a Reference Type (e.g. Class) you should be able to modify properties of the object from within the loop. If T is a value type (e.g. Struct) this would not work since the iteration variable would be a local copy.
I am working on a Windows Store app with the following code:
My Class:
public class WebResult
{
public string Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string DisplayUrl { get; set; }
public string Url { get; set; }
public string TileColor
{
get
{
string[] colorArray = { "FFA200FF", "FFFF0097", "FF00ABA9", "FF8CBF26",
"FFA05000", "FFE671B8", "FFF09609", "FF1BA1E2", "FFE51400", "FF339933" };
Random random = new Random();
int num = random.Next(0, (colorArray.Length - 1));
return "#" + colorArray[num];
}
}
public string Keywords { get; set; }
}
The Code:
IEnumerable<WebResult> results = from r in doc.Descendants(xmlnsm + "properties")
select new WebResult
{
Id = r.Element(xmlns + "ID").Value,
Title = r.Element(xmlns + "Title").Value,
Description = r.Element(xmlns +
"Description").Value,
DisplayUrl = r.Element(xmlns +
"DisplayUrl").Value,
Url = r.Element(xmlns + "Url").Value,
Keywords = "Setting the keywords here"
};
foreach (WebResult result in results)
{
result.Keywords = "These, are, my, keywords";
}
if (control is GridView)
{
(control as GridView).ItemsSource = results;
}
Once the results get displayed the "Keywords" property is "Setting the keywords here". If I put a break point in the foreach loop I can see that the results object is not getting modified...
Any ideas as to what is going on? Am I just missing something obvious? Does IEnumerable behave differently in .NET For Windows Store Apps?
This is known as deferred execution; results is a query that is executed every time you iterate over it. In your case it's evaluated twice, once in the for loop, and a second time when it's databound.
You can verify this by doing something like this
var results2 = results.ToList();
foreach (WebResult result in results2)
{
result.Keywords = "These, are, my, keywords";
}
if (control is GridView)
{
(control as GridView).ItemsSource = results2;
}
You should see that your changes persisted.