When an object is created, a reference is returned, and not the object.
What does this mean?
object a = new object();
Here a holds the reference.
It would be helpful if someone explains the creation of the object, creation of references.
I think of a reference as being like a set of directions to get to a house, where the house represents the object itself.
So if you were to tell someone how to get to your house, you might write down those directions on a piece of paper and give it to them - that's like assigning a reference to a variable.
Coming to your example:
object a = new object();
That's like building a new house (calling the constructor) and then on a piece of paper (the variable a) you write the directions to get to the new house. The paper doesn't have the house itself on it - just directions. If someone copies the contents of the piece of paper, like this:
object b = a;
that doesn't create a second house. It just copies the directions from the piece of paper a to the piece of paper b. Likewise then the two pieces of paper are independent - you could change the value of a to a different set of directions, and it wouldn't change what's on b.
I have an article on this which attempts to explain it another way, which you may find helpful.
The following statement:
object a = new object();
Actually does two different things.
First, new object() allocates the necessary memory to store the instance is allocated on the heap and returns the address on the heap that just got allocated.
Secondly, the assignment is evaluated and assigns the value returned from new to a.
When you say "a holds a reference" it means that a is the memory on the stack (or in registers, or on the heap depending no the lifetime of the reference) that points to the heap location of the instance you just created.
When you instantiate a class with the new keyword you create an object on the heap. It is not referenced by anyone yet. If an object has no references to itself it can be soon garbage collected. To operate with an object you need to reference it. So you create a variable which contains the address of the object(the reference).
With most modern languages you don't have to worry about references vs the object themselves. Back in the day (eg c++) you would have to worry about reference (sometimes called pointers) and even the memory allocated for them. Now the system (and what is called the garbage collector) worries about it for you.
Here is the details. Your example line means the following:
1) allocate memory for object
2) run the constructor
3) put the memory location of that object in the variable "a"
What does the mean to you conceptually as a programmer? Not much, most of the time. In C# you can still think of the variable a as the object. You don't have to worry about it pointing to the object under the hood. Most of the time it does not matter.
Where it matters is when you need to be concerned about the lifetime of the object. Because you have a reference to the object it will not be deallocated which means if it is using a system resource it will continue to do so.
When an object is no longer being referenced it will be deallocated by the garbage collector.
Another tongue-in-cheek analogy for the pile: the object is a helium balloon, and a reference is a string tied to that balloon which you are holding. Saying new object() is equivalent to asking a balloon guy (the memory manager) at the fair (your program) for a new balloon. He may either give you a balloon by means of handing you the string, or he may also tell you that there are no balloons left. You may find the latter very upsetting and run crying from the fair.
You may wish to share the balloon with your sibling, and here the analogy starts to fall apart. This could be seen as both you and your sibling holding onto the same string with your hands, or a second string being tied to the balloon for your sibling. Care must be taken to ensure that those who hold the string(s) tied to the balloon coordinate their movements, otherwise the balloon may be ripped or ruined.
Finally, in a language like C# when you become bored of the balloon, you can simply let go of the string. If others are still holding the string it will not go anywhere, but if they are not it floats harmlessly into a net in the sky, from where the balloon guy periodically collects the released balloons to replenish his stock. In other older languages like C, there is no such net and the balloon guy will never be able to recover the helium in that balloon to make another balloon for someone else. He would really appreciate it if you took the balloon back. This causes other problems: you may return the balloon, but forget that your sibling still wanted it. With their back turned, they don't notice you pulling the string out of their hand and later when they turn and look for it, they will find it is gone and be very upset.
Ridiculous analogy? Yes. Will it stick in your mind? Most likely :)
Related
Suppose I have a loop which creates a new instance of a EF Class to add to databasde table in each loop iteration:
foreach (var record in records)
{
InvestmentTransactionStaging newRecord = new()
{
UserId = UserId,
InvestmentTransactionTypeId = interestRepaymentTransactionTypeId,
InvestmentEntityId = InvestmentEntityId,
Description = record.LoanReference,
Date = DateTime.Parse(record.Date),
};
_context.InvestmentTransactionsStaging.Add(newRecord);
}
Now normally, in the languages I am used to such as php it is not important destroy the instance after the call to _context..Add(), the garbage Collector takes care of it. If I omit this as I have above, would this then potentially cause any issues with memory in C#? Do I need to destroy the instance on each itertation that it is instamtiated and if so how? (I could not use the Disapose method as it complains the method is unavailable.
Created objects are automatically destructed when no longer reachable
Meaning, any object created, lives only as long as the running code is still between curly braces, where it was instantiated
Update - Going deep
As mentioned by computercarguy (as well as in the comments), it's not accurate to say the object only lives inside the code block in which it was declared, cause the object lives as long as there is a reference to it in the program.
Meaning, if you declare an instance called newRecord, and you don't assign it to any other pointer which has been declared outside of that code block in which newRecord was declared, then yes, when compiler exits that code block (and goes through the steps of Garbage Collection), it is removed from the memory, but if there is another pointer, for example oldRecord, and you assign the value (address) of the newRecord to it before the end of the code block, then the object isn't removed from memory, for it is still being pointed to, by a pointer ie oldRecord.
In conclusion: The garbage collector checks for objects that are no longer being used by the application, so there is no point in removing the object manually, because the GC does it for you, if it is safe to remove the object, for it can cause problems when implemented by us imperfect humans ☺
TLDR: Even if you set newRecord to null, you wouldn't have destroyed the class instance. It's still accessible in the _context.InvestmentTransactionsStaging object. (In this case, _context is probably a database.)
Long answer:
I might be getting into the weeds here, but your variable is just a pointer to a memory address where the class instance/object was created. When you null out that variable, you simply simply remove the value of the memory address from the variable, not the object. The object remains if other variables are pointing to the same memory address. Automatic garbage collection happens when that object's memory address is no longer being pointed to by any variables or other objects. This is when things get "destroyed".
This happens in many modern languages, not just C#. It might happen differently in C# than it does in PHP, but it ends up with similar results.
Even saying that the object is destroyed is not 100% correct, since the values aren't usually removed. The memory address is just used for something else and overwritten as needed. That can be within the same program or it could be returned to the OS for it to allocate to another process.
And this doesn't cover the complete lifecycle of objects, but it's the most useful explanation until you need to get into much lower level programming of microcontrollers and other embedded systems.
I'm working on a TCP socket related application, where an object I've created refers to a System.Net.Sockets.Socket object. That latter object seems to become null and in order to understand why, I would like to check if my own object gets re-created. For that, I thought of the simplest possible approach by checking the memory address of this. However, when adding this to the watch-window I get following error message:
Name Value
&this error CS0211: Cannot take the address of the given expression
As it seems to be impossible to check the memory address of an object in C#, how can I verify that I'm dealing with the same or another object when debugging my code?
In C#, objects are moved during garbage collection. You can't simply take the address of it, because the address changed when the GC heap is compacted.
Dealing with pointers in C# requires unsafe code and you leave the terrain of safe code, basically making it as unsafe as C++.
You can use a debugger like windbg, which displays the memory addresses of objects - but they will still change when GC moves them around.
If you want to see if a new instance of your class gets created, why not set a breakpoint in the constructor?
I am convinced with #thomas answer above.
you can add a unique identifier (such as a GUID) property to your object and use that to determine if you have the same object.
you could override the Equals method to compare two objects if they same as below.
public class MyClass
{
public Guid Id { get; } = Guid.NewGuid();
public override bool Equals(object obj)
{
return obj is MyClass second && this.Id == second.Id;
}
}
As already explained, addresses of objects are not a viable means of reasoning about objects in garbage-collected virtual machines like DotNet. In DotNet you may get the chance to observe the address of an object if you use the fixed keyword, unsafe blocks, or GCHandle.Alloc(), but these are all very hacky and they keep objects fixed in memory so they cannot be garbage collected, which is something that you absolutely do not want. The moment you unfix an object, then its address is free to change, so you cannot keep track of it.
Luckily, you do not need any of that!
You don't need addresses, because all you want is a mnemonic for each object, for the purpose of identifying it during troubleshooting. For this, you have the following options:
Create a singleton which issues unique ids, and in the constructor of each object invoke this singleton to obtain a unique id, store the id with the object, and include the id in the ToString() method of the object, or in whatever other method you might be using for debug display.
Use the System.Runtime.Serialization.ObjectIDGenerator class, which does more or less what the singleton id generator would do, but in a more advanced, and possibly easier to use way. (I have no personal experience using it, so I cannot give any more advice about it.)
Use the System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode( object ) method, which returns what is known in other circles as The Identity Hash-Code of an Object. It is guaranteed to remain unchanged throughout the lifetime of the object, but it is not guaranteed to be unique among all objects. However, since it is 32-bits long, it will be a cold day in hell before another object gets issued the same hash code by coincidence, so it will serve all your troubleshooting purposes just fine.
Do yourself a favor and display the Identity Hash Code of your objects in hexadecimal; the number will be shorter, and will have a wider variety of digits than decimal, so it will be easier to retain in short-term memory while troubleshooting.
Lets consider the following scenario in the Single Linked List:-
I have been given the target node, which is going to be deleted.
Lets assume the following data and I am going to receive the object which holds "3", which is the one I am going to delete;
1 -> 2 -> 3 -> 4 -> 5 -> 6
And Class Structure is:-
Class DataHolder
{
int data;
DataHolder nxtPrt;
}
Void Delete (DataHolder currentData)
{
currentData.data = currentData.nxtPrt.data; //Now 3 will be overwritten by 4
(x) currentData.nxtPrt = (y) currentData.nxtPrt.nxtPrt;
//Now the object which belongs to 4 (previously it was 3),
//is pointing to 5;
}
So, now the actual copy of the object 4 is now become useless;
So, now i just want to remove the space allotted to original copy of 4;
But, now I cannot track it also since, I have altered the object to point 5.
So right now, at this point I have lost the actual object 4.
May I Kindly know, is there any way to forcefully ask the object to release its occupied memory like doing in "C" using dealloc,
or I have to depend on the GC to collect the unused space upon its wish.
Thanks in advance.
You're always relying on the GC, there's no way around it. And yes, it will clean up your other objects, as long as there's no reference to them. You can allocate unmanaged memory and deal with it as you see fit but, in that case, why are you using C#? Just use C(++).
But the simplest answer is don't write your own linked list. Just use LinkedList<YourStruct>. Learn your environment - the language(s), the libraries and the runtime. If you're just going to write C code in C#, you're going to hurt, nobody's going to understand your code and you gain hardly any benefit from working in C#. Again, if you don't want to use C#/.NET... don't. There's nothing inherently wrong with C or C++, or with unmanaged languages. Use the best tool for the job.
Don't think in C terms at all. It simply doesn't work in a GC'd/managed environment. Where does memory come from when you allocate it in C? Usually the stack or the heap, with a few bits in registers. In .NET, this is kind of abstracted away, but in practice, you still only have those three locations. However, they work differently. You can't allocate classes or arrays on a stack (there's limited support using unsafe code, but that's it). There's multiple heaps, and apart from the large object heap, they always allocate from the top, similar to a stack. So deallocating a single object has no value whatsoever - if you don't compact the heap to eliminate the free spots, you don't get less memory usage, and you don't get any extra space for new objects.
If class x calls y by going y.create(new z) does the z obj get created in x's stack as well as y's? This is assuming we are passing by value, not ref or ptrs
A couple of things:
The stack/heap is on the process (application) level, not at an object level. The entire application shares one stack (at least in the context of your question), no matter how many objects it is using.
Unless the "z" in your example is a value type (like a struct), it won't ever fully reside on the stack. If "z" is a class, then it "lives" on the heap, with only a reference to it on the stack.
You really should read this short explanation from Jon Skeet, especially "A worked example" towards the bottom.
The object z is created in the applications allocated memory. Each function does not have its own memory area when using new to create objects.
I would suggest that you read up on the content on this page, I certainly find it useful from time to time (ie when i get things mixed up)
I'm trying to make a Tetris-like game in XNA, and currently I'm thinking of what way would be the best to handle it.
This is what I have so far:
I have a class called Block, which has for example texture and color tint.
Then I was planning on having everything in a double array, like:
Block[,] blocks = new Block[10,20];
which would then be the full grid.
And then when the blocks move downwards, I was thinking of doing like this:
blocks[x,y+1] = blocks[x,y];
blocks[x,y] = null;
At first I thought this was a good idea, but now when I've been thinking I'm not so sure. How does it work with the memory and such? Does it create a new object every time I do that or what? Could someone please explain how it actually works when I move an object inside an array?
I'm not really looking for a Tetris-specific answer, I'm just interested in how it actually works.
Thanks.
No, you're just moving pointers around. When you say:
blocks[x,y+1] = blocks[x,y];
what you're essentially doing is swapping the pointer. The object will stay exactly where it is, but now instead of it being at index x,y it'll be at index of x , y+1. When you say
blocks[x,y] = null;
there you're removing the reference to the object x,y and if nothing else is holding a reference, the Garbage Collecter will clean it up.
The first answer above is almost correct, but the assignment is not swapping the pointer, it is duplicating it. After the first line of code there are two references to the object originally referenced at blocks[x,y]. The null assignment removes the original reference, but you still have the new reference living at blocks[x,y+1]. Null that one and the heap object will be fair game for the GC.
If you were storing value types (such as int, string) inside your array, you would indeed be creating a copy of the data each time you copied a value over, because value types are immutable in C#. Since you're storing a class (which is a reference type) in your array, your code is really just making a copy of the pointer, not the whole object.