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.
Related
I am developing a game where 2 players each have many objects from a class called UnitObject, each of which can be on a different Army.
Right now, the player class has a List of UnitObjects and at the same time, each Army has its own List for storing units that belong to it. I am new to c# and I am wondering if, when having hundreds of units, it would be better to have the player have a Dictionary<int, UnitObject> with the int being the id of said unit, so that other classes can have just a List of integers for reference. Do the UnitObjects in the Army duplicate the memory use of the ones in the Player or is it just a reference?
My code could be (very) simplified to:
UnitObject unit = new UnitObject();
army.units.Add(unit)
player.units.Add(unit)
This is an over simplification, my classes have other classes they belong to and is not as simple as to make the player have a list of armies or so. I am just wondering if by doing this, i am using double memory for each object.
UnitObject is a reference type, unlike s struct or [most] primitive objects such as int, which are value types.
Reference objects are allocated independently, either on the the stack or the heap (depending). They are passed by reference: when you add an instance of a reference type (such as an instance of your UnitObject) to a collection, what it added is a reference to the actual object itself. A reference is a single processor word (32- or 64-bit, depending on processor architecture). It's not a pointer, more like a pointer to a pointer, to allow the allocated object to be moved by the garbage collector if need be.
You when you add an instance of your UnitObject to two different collections, they both point to the same instance of UnitType.
And if you pass a reference type to a method, it is passed by reference: any changes made to the passed object by the called function persist once control returns to the caller.
Value types, are passed by value, näturlich, so adding something like an int to a collection means the collection receives a copy of the value. Ditto for passing value types to method: the method receive a copy of the value.
My question concerns the use of objects in C#. I think I understand what's happening, but I want to understand why. For reasons I won't go into, I want to create a temporary copy of an object with its current data (current state). So I thought I could create a new object, assign it the original object, then change the original object. At that point I would have two objects in different states. But what happens is that the copied object ends up looking exactly like the first. Here is some code to illustrate:
Order o1 = new Order();
o1.property1 = "test 1";
Order o2 = new Order();
o2 = o1;
o1.property1 = "test 2";
But at the end of this code, both o1 and o2 have property1 set to "test 2". I think I realize that all objects are just pointers, so if you change one it changes another, but I can't understand why this is, or why it is useful. Is there some fundamental thing I'm missing here? Also, what would be the best way to accomplish what I want to do? Which is: store the state of the object, make changes, then revert if necessary. Hopefully this makes sense.
An object variable in C# is a reference (not a pointer) to a specific object in memory. When you declare
Order o2 = new Order();
you are creating a new Order object in the heap, and allocating a reference to that object to your o2 variable. When you then state
o2 = o1;
you are telling the compiler to make o2 a reference to o1. At this point, the reference to the original o2 object is lost, and the memory for that object will be removed during the next garbage collection sweep.
Henceforth, both o1 and o2 both reference the same object in memory. To copy information from one object to another, you will need to implement a procedure to instantiate a new destination object and copy all of the data from one object to the other. See the MSDN docs on ICloneable for more info.
What you are referring to is the difference between value types and reference types. Apparently your Order object is a reference type, I would assume it is a class.
Classes are reference types meaning they are "pointers". One of the reasons for this is performance as you do not want to copy huge amounts of data every time you assign a variable.
Structures are value types and would be copied in memory when you assign them.
You have 2 solutions :
Use a struct instead of class
Clone your object using either MemberwiseClone if it is very simple, or use your own method if you need to perform a deep clone.
This is by Design. If you want to clone and keep the clone independent i would recommend to Implement a "cloning" mechanism on your types. This can be ICloneable or even just a constructor that takes an instance and copies values from it.
Regarding your question
what would be the best way to accomplish what I want to do? Which is:
store the state of the object, make changes, then revert if necessary
A simple method is to simply serialize the object, e.g. using XMLSerializer. Then if you want to throw away your changes, just deserialize the original object and replace the modified object with the original version.
Use Structures to accomplish your task, Classes are reference type and Structs are Value type.
Classes are stored on memory heap
Structs are stored on stack.
for more info search Structs vs Classes and learn differences
Objects are, by definition, a 'pointer'; they hold a reference to your data, and not the actual data itself. You can assign it a value type though and it will give the appearance of holding the data.
As was mentioned above, understanding Value types vs. Reference types is key.
Java has no concept of any non-primitive data type other than an object reference; since almost anything one can do with an object reference involves acting upon the object referred to thereby, the . operator in Java . Although .net does have non-primitive value types, most .net languages maintain the convention (different from C and C++, which use -> to access a member of a pointed-to object and . to access a member of a structure) that the same . operator is used for both "dereference and access member" and "access value-type member".
Personally, I dislike Java's "everything is an object reference" design, and .net's decision to have value types and reference types use the same . operator to mean very different things doesn't help, but it is what it is.
I understand this topic is answered a lot. My question is specific to the way it is said or asked.
So am I right to say, that code written with a class keyword will be on the managed heap and is a reference type, and code that is written with a struct will be on stack and is a value type?
I used to think like this as well. However, I recently had a nice discussion with Jon Skeet (he may provide more details) and he explained me that a value type may be kept on the heap as well. The key is how long will that variable be used. If it's a short-lived value type variable, it will be left only at the stack. However, if it's used many times, the framework will keep it at the heap to save space at the stack.
IMO, the key difference between reference and value types relies on passing the object to another object or method. If it's a reference type, you are simply sharing its reference. If it's a value type, then you are making a copy of it.
About the subject of short x long-lived variable, here is the full picture:
in the Microsoft implementation of C# on the desktop CLR, value types
are stored on the stack when the value is a local variable or
temporary that is not a closed-over local variable of a lambda or
anonymous method, and the method body is not an iterator block, and
the jitter chooses to not enregister the value.
Source: The Truth About Value Types (it's also on the comments)
Any storage location (local variable, parameter, class field, struct field, or array slot) of a reference type will always either hold null, or else will hold a reference to an object on the heap. A storage location of a value type will hold all public and private fields of that type (a primitive value type is internally stored as a structure with one field, which is declared to be of that same primitive type; a little bit of compiler magic is used to recognize when special-case code must be used to work with that type). For every value type there is a corresponding heap-object type which has the same members; an attempt to store a value type in a reference-type storage location will create a new heap object of the appropriate heap type, copy the contents of the value-type fields to those of the new object, and store a reference to that new object in the requested storage location. This process is called "boxing". It's possible to copy the contents of a boxed heap object's fields to those of a value-type storage location, a process called "unboxing". Note that because boxed value types are accessed using reference-type storage locations, they behave like reference types rather than class types. C# tries to pretend that the type of a value-type storage location and the type of a boxed value-type instance are the same type, but the two types behave somewhat differently; pretending that they are the same simply adds confusion.
I've been told that when you pass an Object to a method,
it's passed "by value". I made a little test to examine it:
Point p = new Point(1, 1);
Circle c = new Circle(p);
p.x = 999;
Console.WriteLine(c.p.x);
the code above prints "999", but I thought the object is copied to the method
I've been told that if you're not using "ref" (or "out") the method get the value
of the object.
can someone make it clear to me?
thanks,
socksocket
Assuming Point is declared as class, not p itself is copied, the reference to p is copied. So it's still pass by value. You pass the value of a reference.
When saying Point p = new Point(1, 1); (and if point is a reference type), one might think it is a variable containing a Point, but in fact it is a variable containing a reference to a Point that is stored somewhere else.
C# is pass-by-value - the reference value is passed in the normal case, that is. ( which means that it is a new reference to the same object)
Point is structure, so passed by value.
In .NET, there are two categories of types, reference types and value types.
Structs are value types and classes are reference types.
The general different is that a reference type lives on the heap, and a value type lives inline, that is, wherever it is your variable or field is defined.
A variable containing a value type contains the entire value type value. For a struct, that means that the variable contains the entire struct, with all its fields.
A variable containing a reference type contains a pointer, or a reference to somewhere else in memory where the actual value resides.
This has one benefit, to begin with:
value types always contains a value
reference types can contain a null-reference, meaning that they don't refer to anything at all at the moment
Internally, reference types are implemented as pointers, and knowing that, and knowing how variable assignment works, there are other behavioral patterns:
copying the contents of a value type variable into another variable, copies the entire contents into the new variable, making the two distinct. In other words, after the copy, changes to one won't affect the other
copying the contents of a reference type variable into another variable, copies the reference, which means you now have two references to the same somewhere else storage of the actual data. In other words, after the copy, changing the data in one reference will appear to affect the other as well, but only because you're really just looking at the same data both places
When you declare variables or fields, here's how the two types differ:
variable: value type lives on the stack, reference type lives on the stack as a pointer to somewhere in heap memory where the actual memory lives
class/struct-field: value type lives inside the class, reference type lives inside the class as a pointer to somewhere in heap memory where the actual memory lives.
See MSDN and this tutorial is similar to your Circle / Point / Axises Example.
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.