Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens to the previous "new" operator?

Tags:

c#

DispatcherTimer dt = new DispatcherTimer();
dt.Interval = new TimeSpan(0, 0, 0, 0, 100);
dt.Tick += new EventHandler(dt_dt);

I have a question about the new keyword. I have a DispatcherTimer which I set to an interval. Let’s say the user wants to change the interval.

dt.Interval = new TimeSpan(0, 0, 0, 0, 50);

So, what happens to the very first new TimeSpan? Is it still there? Or does the new one override the previous? I don’t think it does.

And if I want to change the interval, is the new keyword the only way to declare a new TimeSpan? I am asking this, since I’m not sure whether it’s actually okay or even right to declare a new TimeSpan every time the value changes.

like image 267
Raiho Avatar asked Apr 03 '18 11:04

Raiho


People also ask

What does the new operator return?

In short: The new operator returns the unique address of the allocated object. When you allocate an array of objects the address of the first object is returned.

What happens when we use new and delete operator?

Memory that is dynamically allocated using the new operator can be freed using the delete operator. The delete operator calls the operator delete function, which frees memory back to the available pool. Using the delete operator also causes the class destructor (if one exists) to be called.

What happens if new operator fails?

What happens when new fails? Explanation: While creating new objects, the new operator may fail because of memory errors or due to permissions. At that moment the new operator returns zero or it may throw an exception. The exception can be handled as usual.

Is it possible to overload the new operators?

New and Delete operators can be overloaded globally or they can be overloaded for specific classes.


Video Answer


2 Answers

You have class (DispatcherTimer) which has field of type TimeSpan, and TimeSpan is a struct.

Since it's a struct - it's "embedded" into instance of DispatcherTimer. So instance of DispatcherTimer looks in memory like this:

<various metadata>...<contents of timespan>...

If it were class (reference type), it would look like this:

<various metadata>...<reference to timespan>...

When you do

dt.Interval = new TimeSpan( 0, 0, 0, 0, 50); 

Instance of TimeSpan is allocated (on stack in this case) and copied to the memory region of DispatcherTimer instance allocated for Interval, overwriting what was there before.

So we had

<various metadata>...<contents of timespan 1>

and now we have

<various metadata>...<contents of timespan 2>

That means old interval timespan is simply overwritten, it will not be collected by garbage collector because there is just nothing to collect (contrary to what accepted answer claims).

For that reason doing that in a tight loop is also not a problem (though of course there is no reason to). Consider this code:

class ClassWithRefField {
    public TestClass Field;
}

class ClassWithStructField {
    public TestStruct Field;
}

class TestClass {
    public TestClass(int payload) {
        Payload = payload;
    }
    public int Payload;
}

struct TestStruct {
    public TestStruct(int payload)
    {
        Payload = payload;
    }
    public int Payload;
}

Then if you do:

static void Main(string[] args) {
    var f = new ClassWithRefField();
    while (true) {
        f.Field = new TestClass(1);
    }            
}

And observe process memory even in process explorer in windows - you will see that memory constantly grows and drops. That's instances of TestClass are created on heap and collected by garbage collector.

However if you do this:

static void Main(string[] args) {
    var f = new ClassWithStructField();
    while (true) {
        f.Field = new TestStruct(1);
    }            
}

Memory in process explorer will stay absolutely constant, because the same region of memory is constantly overwritten, so there is nothing to collect. This loop can run forever.

And yes - it's ok to do it the way you are doing.

like image 90
Evk Avatar answered Oct 21 '22 07:10

Evk


Well, there are multiple things to consider here. Yes, it does create a second instance of the TimeSpan struct. Since the first one isn't referenced anywhere, it will go out of scope and will be cleaned up by the garbage collector. No harm done.

If TimeSpan would have been a class, you probably change one of the properties, but it is a struct, and structs are usually immutable, meaning you can't change their value. (This is due to multiple reasons, I would suggest to read up on that)

So the only option you have here is to create a new TimeSpan struct instance. That is no problem if you don't do it in a tight loop (creating a low of new instances in a very short time, consuming lots of memory).

like image 31
Patrick Hofman Avatar answered Oct 21 '22 05:10

Patrick Hofman