Simple old school C# question: Is an ArrayList an Array or a List? The differences between the two are enormous, so I'm curious if anyone knows the way that ArrayLists store data?
ArrayList behaves like a list (in particular, its count of elements can grow, unlike an array), but it's backed by an array, which will be dynamically resized as needed. Hence the name ArrayList.
Things that behave like lists don't have to be backed by arrays (they could be linked lists, for example), but ArrayList is.
.NET Framework contains a data structure that provides this functionality—the System.Collections.ArrayList classThe ArrayList maintains an internal object array and provides automatic resizing of the array as the number of elements added to the ArrayList grows. Because the ArrayList uses an object array, developers can add any type—strings, integers, FileInfo objects, Form instances, anything.
While the ArrayList provides added flexibility over the standard array, this flexibility comes at the cost of performance. Because the ArrayList stores an array of objects, when reading the value from an ArrayList you need to explicitly cast it to the data type being stored in the specified location. Recall that an array of a value type—such as a System.Int32, System.Double, System.Boolean, and so on—is stored contiguously in the managed heap in its unboxed form. The ArrayList's internal array, however, is an array of object references. Therefore, even if you have an ArrayList that stores nothing but value types, each ArrayList element is a reference to a boxed value type.
you'll be able to invoke ArrayList specific methods and use ArrayList specific members in addition to those inherited from List.
Apart from other differences, one more difference is that ArrayList are not strongly typed i.e array list can add any type of element which is derived from object as shown in the code below
ArrayList myArrayList = new ArrayList();
myArrayList.Add(1);
myArrayList.Add("test");
but array and IList are strongly typed i.e we can take advantage of compile type checking in both of them e.g
int[] myarray = new int[5];
myarray[0] = 1; // This is correct
myarray[1] = "test"; // compile time error
Related
public void FindClosestEnemy()
{
List<GameObject> pList = GameObject.FindGameObjectsWithTag("Player");
pList.OrderBy(obj=>Vector3.Distance(FindLocalPlayer().transform.position,
obj.transform.position)).ToList();
}
I do not understand the difference between the two lists. How do I convert the 'UnityEngine.GameObject[]' list to the System.Collections.Generic.List>UnityEngine.GameObject<
GameObject.FindGameObjectsWithTag returns an array of GameObjects.
An array in C# is a data structure that stores multiple objects of the same type.
A list is a generic collection of objects.
While an array and a list are very similar in concept, there are different between the two in terms of data access and usage. Generally an array is only populated once at creation and only read thereafter, while a List can have it's elements altered at any time (some caveats apply).
This StackOverflow question summaries why you might want one over the other: Array versus List<T>: When to use which?
In your specific case, you want to apply some Linq ordering to your GameObject collection so you need to convert the array received from FindGameObjectsWithTag to a list.
You can do this in several ways. The easiest is to use a constructor overload on list to assign the entire array at once:
GameObject[] gameObjectArray = GameObject.FindGameObjectsWithTag("Player");
List<GameObject> gameObjectList = new List<GameObject(gameObjectArray);
Some other options are available here: Conversion of System.Array to List
As Steve rightly explain but i want to answer in a bit different manner:
Actually in your code you are assigning array type object (GameObject.FindGameObjectsWithTag("Player")) into list type (List<GameObject> pList ) object which is not implicitly support by the compiler. You have to convert your list into an array type:
List<GameObject> pList = new List<GameObject>(GameObject.FindGameObjectsWithTag("Player"));
After this, you will be able to use your code.
Now for the first part of the question
I do not understand the difference between the two lists.
Actually you are asking about Different b/w array and list and the main difference you should need to keep in mind that when you have fixed length of data then, you should use array and if you have variable lenght of data then you use List.
You can also find great detail on this topic on stackoverflow
Array versus List: When to use which?
How and when to abandon the use of arrays in C#?
Why do we use arrays instead of other data structures?
List explaniation by MSDN
Arrays considered somewhat harmful
Should I user array or list
Is it possible to fully remove Array in C# but not to fill it with 0's:
for(int i=0;i<a.Length;i++)
{
a[i]=0;
}
or Array.Clear(a,0,a.Length);
But to clear it in a way that List.Clear() does so that it's size will be 0 again like before filling.
I tried
a=new int[15]; but prevous values where still there. Thanks!
Arrays in C# are fixed-length; you cannot change the size of an array. You can allocate an array of a different size and copy the elements in order to simulate resizing (this is exactly what List<T> does internally), but you cannot "clear an array" in the sense that you reduce it to zero elements.
I tried a=new int[15]; but prevous values where still there.
The previous values cannot possibly still be there, because this allocates a new int array of 15 elements, where all elements are zero.
Note that this does not alter the array that a referenced; rather, it creates a new array and stores a reference to it in a. So if you initialized a from another array variable, they would have referred to the same array, but after assigning a new array to a the other variable would continue to point to the old array. Perhaps this is where the "previous values" are coming from.
var a = new int[] { 1, 2, 3 };
var b = a;
// a and b now reference the same array.
a = new int[] { 4, 5, 6 };
// a is now {4,5,6} but b remains {1,2,3}
As others have said, it depends on the type semantics that you're putting into the array.
Value types (such as int, bool, and float) are ... well, values. They represent a quantity, something tangible, a state. Thus, they are required to be known at compile time and have a default value.
By contrast, reference types (basically every class) don't actually hold any values themselves, but "group" data together by means of reference. Reference types will either point to other reference types, or eventually to a value type (which holds actual data).
This distinction is important to your question. List<T> is a dynamically sized collection that can grow or shrink without creating a new object because of how it is implemented. Each element in the list points to the next element, thus it's size cannot be known ahead of time.
Arrays are a fixed-size collection that are declared to be a specific size. The type of array determines how much memory is reserved by the system. For example a byte[] of 100 elements will consume less memory than an Int64[] array of 100 elements. Thus, the system needs to know ahead of time how many bytes to reserve in total, which means it needs a default value to "fall back" on to satisfy compile-time checking. Where T[] is a reference type/class, this is null. For value types, this is usually 0 (or default(T)).
If you wanted to remove all the values of an array, similar to how List.Clear() works, you can do int[] a = new int[0];, but note that you are creating an entirely new array and reallocating the memory for them (hence the keyword new). Other objects will need to reference this new array. By design, you can't simply resize an array. A list is a mutable collection and supports changing the number of elements. You could also try int[] a = null, but this sets it to no object at all, which is again, something different.
It depends whether the array's elements are Value type or Reference type.
In your case it is value type so you'll have to have some value in it. You can not assign null to it.
Because value type objects have some default values.
object[] objs = new object[]{"one","two","three"};
Are the strings stored in the array as references to the string objects
[#] - one
[#] - two
[#] - three
or are the string objects stored in the array elements?
[one][two][three]
Thanks.
Edit: Sorry, my fancy diagram failed miserably.
String objects can never be stored directly in an array, or as any other variable. It's always references, even in a simple case such as:
string x = "foo";
Here the value of x is a reference, not an object. No expression value is ever an object - it's always either a reference, a value type value, or a pointer.
Jon Skeet describes the actual implementation very well, but let's consider why it would be nonsensical for the CLR to store strings directly in an array.
The first reason is that storing strings directly in the array would harm performance. If strings were stored directly in an array, then to get to the element 1000 of the array the CLR would have to walk through the bytes of all the strings in the array until it reached element 1000, checking all the while for string boundaries. Since strings and any other reference types are stored in arrays as references, finding the right element of the array requires one multiplication, one addition, and following one pointer (the notion of a pointer here is at the implementation level, not the programmer-visible level). This produces much better performance.
The second reason that strings cannot reasonably be stored directly in an array is that C# arrays of reference type are covariant. Let's say that strings were stored directly in the array generated with
string[] strings = new string[] {"one", "two", "three"};
Then, you cast this to an object array, which is legal
object[] objs = (object[])strings;
How is the compiler supposed to generate code that takes this possibility into account? A method that takes an object array as a parameter can have a string array passed to it, so the CLR needs to know whether to index into the array as an object array, or a string array, or some other type of array. Somehow, at runtime every array would have to be marked with the type declaration of the array, and every array access would have to check the type declaration and then traverse the array differently depending on the type of the array. It's far simpler to stick with references, which allow a single implementation of array accesses and improve performance to boot.
They're stored internally as references. A copy of the string is stored, and anywhere that string is used, there's a reference to the same stored string. (this is one of many reasons that strings are immutable; otherwise, modifying one instance of a string would modify everywhere it appeared)
all the primitive types are stored directly into a array but all other object or reference types are stored as memory references. This is true for all Objects not limited to Strings.
int[] x = new int[5];
x[0] = 1;
x[1] = 2;
x[2] = 3;
x[3] = 4;
x[4] = 5;
System.Collections.ArrayList y = new System.Collections.ArrayList(5);
y.Add(1);
y[2] = 2;
The above gives a run time exception "Index was out of range. Must be non-negative and less than the size of the collection."
Why is this so ? Can't we add data into ArrayList using index same as int[] Array? Please provide me with some pointers to understand the reason behind this implementation.
Your ArrayList only has one entry in it, and so index 2 is out of range. ArrayList#Add adds to the list. Your list has an initial capacity of 5 because you called the ArrayList(Int32) constructor, but you've only added one actual entry to it (which will be at index 0).
The only thing you seem to have misunderstood is what the ArrayList constructor does. new ArrayList(5) does not create an ArrayList with five elements, as opposed to new int[5], which does create an array with five elements (all having the value zero). A newly-created ArrayList is always empty, so any attempt to use [] to set the value of any element will crash, because there are no elements. This is the same behavior as a regular array if you had created an array by saying new int[0] - any attempt to index into it would crash. The only way to get a five-element ArrayList is to either use the constructor that takes a (five-element) collection as a parameter (as #Stilgar and #Kelon showed), or by calling e.g. Add(0) five times. After having done this, you can access x[0], x[1], ..., x[4].
What does new ArrayList(n) do, then? It creates an ArrayList of size zero, but where the internal array that is used to store the values is given the size n, so that we can add n elements before the internal array must be replaced by a bigger one (which takes a little bit of time, which is why you in high-performance scenarios might want to use this constructor if you know how big the list will eventually become).
new ArrayList(5) just allocates memory for 5 entries. That's all. You still have to add or insert to a list - it's not the same as an array.
Maybe you need to use a collection rather than an array like a List<int>();
As for why see this
http://msdn.microsoft.com/en-us/library/k2604h5s(v=vs.80).aspx
Class library designers might need to
make difficult decisions about when to
use an array and when to return a
collection. Although these types have
similar usage models, they have
different performance characteristics.
In general, you should use a
collection when Add, Remove, or other
methods for manipulating the
collection are supported.
For more information about using
collections, see Collections and Data
Structures.
Arrays initializes the memory with default values. Lists have different semantics. They are supposed to manage their size dynamically. The capacity you've provided (5) is purely optimization based on the specific list implementation. Not every IList implementation would have the same internal representation. What if the implementation was a LinkedList? You need to think about the concept of the data structure List not about the particular implementation.
If you want to assign values there are plenty of ways to initialize a list. You can pass an array to the constructor or use the collection initializers from C# 3.0. And please use List instead of ArrayList.
//Collection initializer
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
//passing array as an argument to the constructor
int[] ints = new[] { 1, 2, 3, 4, 5 };
List<int> list2 = new List<int>(ints);
Try
new ArrayList(new int[5]);
this initializes the ArrayList with 5 given default entries.
But
y.Add(1); // would add a 6t entry
You can specify the capacity when creating the ArrayList, but this is only so that the object can allocate space internally, the initial size of the list is still zero.
The difference between an ArrayList and an array is that the size of the list is dynamic. You can add and remove items, which is not possible with an array. It makes sense for a dynamically sized collection to start with the size zero, instead of filling it with zero-values.
Note: The ArrayList class is practically obsolete; you should use the generic List<T> class instead, which performs better and is easier to use, especially for value types like int.
I know I can add object of any type to an ArrayList instance. If I get it right, then reference types are casted to objects (value types are boxed). Also, does an ArrayList actually store lists of objects of reference type object?
Internally the ArrayList class uses a fixed size array object[] (object array) for storage. When you add elements those elements are automatically copied to their respective indexes in the array. When the max size is reached a new array is created with a larger size and the elements are recopied. So it's just a convenience wrapper around a static object array.
An ArrayList does not store objects, but merely the references to those objects.
An ArrayList is essentially a wrapper around an object[], with functionality to track space in the array and grow it (double it) as necessary. Note that usually List<T> is preferred, but to answer the question: yes, it just stores the references to the objects, which may well be boxed value-types.
A List<T> is pretty much the same, but around a T[], which means value types can be stored without boxing. Reference-types are still stored as references. You also get more type safety; i.e. you can't add the wrong thing nor cast a retrieved item improperly.
ArrayList is similar to List<object> and was created before .NET had generics.
It can store anything that derives from object, which is all reference and value types. So you could use it to store a lists of objects.
The internal storage for an ArrayList is an object array (object[]).
When storing reference types in the ArrayList, the reference is just cast to object and stored in the array. The reference type instance itself contains information about it's type, so it's possible to cast it back to the actual type when you get it from the ArrayList.
Value types are boxed inside an object, and the reference to that object is stored in the array. The object contains information about what type the value is, so that it can be unboxed correctly when you get it from the ArrayList.
They store any object.
Meaning it's possible to fill them with strings, integers, classes as long as they have been instantiated as an object.