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.
Related
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
I have a Dictionary<int, Product>. If the same Product is added to more than one key is an new instance of that object stored for each key? Or just a reference to the original object?
This collection is very large and each product will have between 1-10 Keys to it. My primary concern is memory allocation.
If Product is a reference type (class and not struct), only a reference will be stored.
No, it should use the same reference to the original object.
I'm not entirely certain how it will behave if the Dictionary is serialized/deserialized, however.
The Dictionary will store a copy of the the value of the key that you pass it. It wouldn't be possible for it, or any other collection/container for that matter, to store a reference to any value as it is possible for the container to outlive the variable that you tried to store in it.
Now, as others have said, if the type of the value is a reference type, the value of the variable is just a reference, so you're just storing a copy of the reference to the variable. If the Type of the value of the dictionary is a value type then the actual value will be copied.
reference types are stored as references always. no one is going to guess what "clone" logic you intend for your type. if you need copies, you will have to create them on your own before placing to containers, passing to other functions and so on.
value types are copied (simplistically byte representation copy is created, however all reference values will still be references), unless passed as ref to functions. for containers though they will be copies. unless you create a reference type wrapper for them.
I want to clear concepts regarding Memory allocation of ArrayList vs Generic List, if both are value type and if both are reference type. Could any one hhelp to clear out?
The only difference in memory use is when you store a Value type. The ArrayList will have to Box (copy) the value. A boxed value will be placed on the Heap, consuming at least an extra header block (ca 20 bytes).
But this will only be significant when you store many millions of items, not something you do all the time.
They are both reference types. The only difference is that ArrayList is weakly typed. Value types such as int, bool etc that are stored in it are boxed into the object type. Then, you unbox them when you cast each item in the ArrayList.
Because everything is boxed into an object, you can store objects of different types in an ArrayList.
Generic List is strongly typed, that is, it can store objects of the same type. There's no boxing, so it's more efficient.
The boxing process allocates more memory to encapsulate the object into the weak type object.
If you stored only objects of reference types in the ArrayList, then boxing is not used, rather another mechanism is used called reference conversion.
ArrayList is a Reference Type,but not Typesafe and less efficient
List<T> or Generic list is a Reference Type,but is Type Safe and efficient
Here is the SO post on Memory Allocation of Reference Types
How memory is allocated to reference types in C#?
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.
All types are derived from the Object class, but the value
types aren’t allocated on the heap. Value type variables actually contain
their values. so how then can these types be stored in arrays and used in
methods that expect reference variables ? Can somebody please explain me how these value types are stored on heap when they are part of an array?
Boxing and Unboxing. Also see Here for info pertaining to arrays specifically (part way down). Note this is for object arrays, a valuetype array (e.g. int[]) doesn't have any (un)boxing.
Have a look at this question:
Arrays, heap and stack and value types
You can pass the instance of a value type to a method expecting an object (ref class). In this case boxing and unboxing happens.
Value type arrays do not require boxing or unboxing!
The CLR handles arrays of value types specially. Of course an array is a reference type which is allocated on the heap, but the value type values are embedded into the heap record (not on the stack).
Similarly, when a reference type class contains a value type field, the value of the field is embedded into the record on the heap..
Value types may be allocated on stack.
This can happen only if they are in parameters or local variables or fields in a another value type which is.
Value types in arrays and fields in classes are stored locally in array or class, instead of pointer being stored there - value types result in more local memory access (performance improvement)
and in case of arrays value n is right after value n-1 in memory, something which is not guaranteed with objects in array of reference types (including boxed values in array of object - also no grantee of continuity). In arrays of reference types it is the references that are continual.