I'm building a menu in my WinForm app and i was doing something like :
MenuItem[] items = new MenuItem[] { };
And after :
for (int namesIndex = 0; namesIndex < menuNames.Length; namesIndex++)
{
MenuItem item = new MenuItem(menuNames[namesIndex]);
for (int entriesIndex = 0; entriesIndex < menuEntries.GetLength(1); entriesIndex++)
{
item.MenuItems.Add(menuEntries[namesIndex, entriesIndex]);
}
items[namesIndex] = item;
}
And an IndeOutOfRangeException is thrown :
After this annoying exception i modified the array declaration with this :
MenuItem[] items = new MenuItem[] { null };
and everything works like a charm.
And now the question : Does anyone out there knows why the above array declaration works, and the other doesn't?
Thanks alot
You're using array initializers to construct the array, so the length of the array will be given by the data you provide.
The first example declares an array with a length of zero as you don't provide any elements. I.e. it cannot contain any elements.
The second example declares an array of length one.
MenuItem[] items = new MenuItem[] { };
This creates an array with 0 items in it.
MenuItem[] items = new MenuItem[] { null };
This creates an array with 1 item in it (it's null, but that still counts).
You probably want to initialize for the number of items you want (new MenuItem[menuNames.Length], for example). Or use new List<MenuItem>() instead, and call Add().
"Everything works like a charm" only to the extent that menuNames has exactly one item. You need to change the code as follows to make it work:
MenuItem[] items = new MenuItem[menuNames.Length];
The reason you saw a crash in the first case is that you created an array with zero items, while in the second case you created an array with one item. If menuNames has more than one element, your code would start crashing again.
Your for loop iterates over compares the loop variable to menuNames.Length, while your using the indexer of the items array. One of the two is wrong.
Additionally, if you want to be adding additional items to a collection, then you should almost certainly be using a List, not an array.
Related
I create the following array like this:
array<UInt16>^ temp = gcnew array<UInt16>(1000);
How do I determine if this entire array has been filled with zero or not.
I think I may be able to use TrueForAll(T) but I'm not sure.
var allElementsAreZero = temp.All(o => o == 0);
Simple as that.
It'll return when it finds one that doesn't satisfy the condition, so may not necessarily iterate through your whole collection:
"The enumeration of source is stopped as soon as the result can be determined."
https://msdn.microsoft.com/en-us/library/bb548541(v=vs.110).aspx
This should work properly (here I used LINQ):
IEnumerable<int> values = new List<int>(); // Or use any array type instead of List.
... Add your values here ...
var allAreZero = !values.Any(v => v != 0);
P.S. the array class inherits IEnumerable.
And here is a solution with foreach:
var isAllZero = true;
foreach (var value in values)
{
if (value != 0)
{
isAllZero = false;
break;
}
}
UPDATE
The really difference between TrueForAll, and my LINQ code is: LINQ code uses the fluent (or maybe also query) syntax, where TrueForAll is just a normal function where you send the array as a parameter.
initialize a counter from 0 then use for loop to interate through the array and increment the counter whenever it finds 0, and at the end compare the counter with size of array if its equal, it has all zeros
Reading the C++/CLI specification, it has been filled with
0s because you created it with a "new-expression" and the default value of the element type is 0.
24.2 CLI array creation
CLI array instances are created by new-expressions containing gcnew (§15.4.6) or …
Elements of CLI arrays created by new-expressions are always initialized to their default value.
I have an array of List types:
List<object>[] vector = new List<object>[3];
The first List contains strings:
// Get word lists together, remove duplicates
var words = tableA.ToList().Union(tableB.ToList());
// Sort words
words = words.OrderBy(s => s, StringComparer.CurrentCultureIgnoreCase);
// Add words to the vector first slot
vector[0] = words.ToList<object>();
Now, I want to add ints to the second and third lists, but I get an error here:
vector[1].Add(tableA.GetValue(keyword));
vector[2].Add(tableB.GetValue(keyword));
GetValue() returns an int. But when I add these ints to the vector Lists it throws error:
ERROR Caught: Object reference not set to an instance of an object.
How should I add the ints to the List? Or is there some other data structure I should use instead for the vector? I feel there is some trivial cast I'm missing but I haven't been able find a solution.
I'm not an expert in C#, but i think i understand.
When you write :
List<object> vector = new List<object>[3];
you create a table of List with a size of 3.
You can put something into each slot of this array, but each "slot" still refers to no instance after this first line of code.
When you write
vector[0] = words.ToList<object>();
You put somehting into the first slot of vector list. But [1] and [2] are still empty. And
vector[1]
refers to a reference not set to an instance of an object. In short terms, it refers to nothing.
You must initialize each vector index value before add value. Thanks
When writing var a = new List<object> you´re only declaring that a is a list holding some (in your case three) items. However you don´t determine what stands in those three elements. You´d have to out some values into every single item, before you can anything with it (e.g. call any method).
You´re allready putting a list into the first item, however the elements on index one and two remain null causing a NullReferenceException when calling a method like the following:
vector[1].Add(...);
So you should initialize the value at index oe and two before:
vector[1] = new List<int>();
vector[2] = new List<int>();
But still you can´t do much with the list, because it is of type object, so you´d have to cast every element to the actual type:
((List<int>)vector[1]).Add(myInt);
Anyway I doubt storing three completely different lists within one single list alltogether is a good idea. Maybe you should define a class with the three lists as members instead:
class MyClass
{
public List<string> Words { get; set; }
public List<int> NumbersA { get; set; }
public List<int> NumbersB { get; set; }
}
A task that I can't seem to solve, even after hours and hours of trying.
Basically, I have a phonebook that takes input from the user: name and number (both string type), which becomes a Contact.
I'm supposed to store the Contact in an Array, and the user shall both be able to add and also delete data (Contact) from the array, via the methods Create and Delete.
I made an own Repository class to handle the data (Contact also has an own little class), but I used List to store the data, so I could simply use Add and Remove, so my code looks like this:
public class Repository
{
List<Contact> storagelist;
public Repository() {
storagelist = new List<Contact>();
}
public void Create(Contact item) //Adds the item to the list
{
storagelist.Add(item);
}
public bool Delete(Contact item) //Removes the item
{
if (!storagelist.Contains(item))
return false;
storagelist.Remove(item);
return true;
}
}
What I am looking for, is how do exactly this, have these 2 features of adding and removing a Contact, but store the data in an Array instead.
Since arrays (to my knowledge) has to have a fixed, pre-defined size I have no idea how it could be used in exactly the same way as the List. The array size shall always be the same as the amount of Contacts that are stored, but how can this be done when an array's size is fixed??
So, how to create an array, that always has the same size as the amount of Contacts that are stored, and how to Add and Remove to/from this array?
Help is very much appreciated!
EDIT: Thanks for all responses! Every answer was helpful in the process (Omar and person66 in particular!).
I solved the Removal by "moving" the entire array after the delete-element, to 1 index lower, and finally resizing the array to be smaller. Like so:
int deleteIndex = Array.IndexOf(storagelist, item);
for (int index = deleteIndex + 1; index < storagelist.Length; index++)
{
storagelist[index - 1] = storagelist[index];
}
Array.Resize(ref storagelist, storagelist.Length - 1);
You are right in that array sizes are fixed. You can, however, use Array.Resize() to create a new array of the specified size with all the current array data. So for adding you would resize to 1 larger and add the new contact at the end. For removing you will have to use a loop to shift all the elements in the array past the one being removed back one spot, then resize it to be 1 smaller.
EDIT: A simpler option for removing would be to use Array.Copy():
Array.Copy(a, deleteIndex + 1, a, deleteIndex, a.Length - (deleteIndex + 1));
Array.Resize(ref a, a.Length - 1);
A list is a much better solution to this problem, I don't know why you would ever want to use an array for this.
A List just ends up using an array for it's storage anyway. The way a list works is it is initializes an array with a certain amount of storage then if it's capacity is exceeded it recreates an array with a larger size and copies the elements back. You could try this approach, except you'd just be recreating what a list does.
The other option is just declare an arbitrarily large array of 100,000 elements or so. A number which you know will not be exceeded.
For size you can write your own function which keeps track of the number of contacts in the array.
You can use a generic list. Under the hood the List class uses an array for storage but does so in a fashion that allows it to grow effeciently.
Take a look at this link for more details, it can be helpfull.
var contacts = new[]
{
new { Name = "Foo", Phone = "9999999999" },
new { Name = "Bar", Phone = "0000000000" }
};
You can create an array of anonymous object and then use linq to delete objects from array.
You can create a new object and insert into anonymous object variable.
This question already has answers here:
Remove element of a regular array
(15 answers)
Closed 9 years ago.
string[] columns
I want to delete the item on an index specified by a variable of type int.
How do I do this ?
I tried
columns.RemoveAt(MY_INT_HERE);
But apparently this does not works.
Array is immutable class, you can't change it, all you can do is to re-create it:
List<String> list = columns.ToList(); // <- to List which is mutable
list.RemoveAt(MY_INT_HERE); // <- remove
string[] columns = list.ToArray(); // <- back to array
May be the best solution is to redesign your code: change immutable array into List<String>:
List<String> columns = ...
columns.RemoveAt(MY_INT_HERE);
If you don't want to use linq you can use this function :
public string[] RemoveAt(string[] stringArray, int index)
{
if (index < 0 || index >= stringArray.Length)
return stringArray;
var newArray = new string[stringArray.Length - 1];
int j = 0;
for (int i = 0; i < stringArray.Length; i++)
{
if(i == index)continue;
newArray[j] = stringArray[i];
j++;
}
return newArray;
}
You use it like that : columns = RemoveAt(columns, MY_INT_HERE)
You can also make it to an extension method.
You cannot delete items in an array, because the length of a C# array is fixed at the time when it is created, and cannot be changed after that.
You can null out the corresponding element to get rid of the string, or use LINQ to produce a new array, like this:
columns = columns.Take(MY_INT_HERE-1).Concat(columns.Skip(MY_INT_HERE)).ToArray();
You need to add using System.Linq at the top of your C# file in order for this to compile.
However, using a List<string> would be a better solution:
List<string> columns;
columns.RemoveAt(MY_INT_HERE);
Try one of the following (depending on what you need):
columns[MY_INT_HERE] = null;
columns[MY_INT_HERE] = string.Empty;
...otherwise you'll just have to create a new array which has a length of 1 less than your current array, and copy the values over.
If you want something more flexible, you might use a something like a List<string>, where you can use RemoveAt()
Arrays are faster for the computer to work with but slower for a programmer. You will have to find that value with a loop or some other means, then set that position to null. You will end up with an empty space in the array. You could reallocate the array etc etc...
What is easier to use for relatively small amounts of data is a List. You can do myList.RemoveAt(100); and it will work nicely.
You can not delete it.You can recreate the array or I advice you to use List<string> for the same.
List<string> columns = new List<string>();
columns.RemoveAt(1);
It will remove the 2nd element from your List<String> columns
I have a struct in C# and I define and array list of my struct based on my code that I express here. I add items in my array list, but I need to delete a few rows from my list too. Could you help me how can I delete item or items from my struct array list:
public struct SwitchList
{
public int m_Value1, m_Value2;
public int mValue1
{
get { return m_Value1; }
set {m_Value1 = value; }
}
public int mValue2
{
get { return m_Value2; }
set {m_Value2 = value; }
}
}
//Define an array list of struct
SwitchList[] mSwitch = new SwitchList[10];
mSwitch[0].mValue1=1;
mSwitch[0].mValue2=2;
mSwitch[1].mValue1=3;
mSwitch[1].mValue2=4;
mSwitch[2].mValue1=5;
mSwitch[2].mValue2=6;
Now how can I delete one of my items, for example item 1.
Thank you.
Arrays are fixed length data structures.
You will need to create a new array, sized one less than the original and copy all items to it except the one you want to delete and start using the new array instead of the original.
Why not use a List<T> instead? It is a dynamic structure that lets you add and remove items.
You will need to move elements around and resize the array (which is expensive), since there is some complexity there you going to want to hide it in class that just presents the collection without exposing the implementation details of how its stored. Fortunately Microsoft has already provided a class that does just this called List<T> which along with a few other collection types in System.Collections.Generic namespace meet most common collection needs.
as a side note, you should use auto-properties instead of the trivial property style that you ha
That's not possible, because an array is a fixed size block of elements. Because structs are values types and not reference types, you also can't just set the element zo null. One option would be to create a new smaller array and to copy your remaining values to the new array. But the better approach would be to use a List in my opinion.
If you really, really want to use arrays and move things around, here are some examples of how to do it:
{
// Remove first element from mSwitch using a for loop.
var newSwitch = new SwitchList[mSwitch.Length - 1];
for (int i = 1; i < mSwitch.Length; i++)
newSwitch[i - 1] = mSwitch[i];
mSwitch = newSwitch;
}
{
// Remove first element from mSwitch using Array.Copy.
var newSwitch = new SwitchList[mSwitch.Length - 1];
Array.Copy(mSwitch, 1, newSwitch, 0, mSwitch.Length - 1);
mSwitch = newSwitch;
}