16

NOTE: I'm interested in C#,Java and C++ most, but as this is the more academic question any language will do.

I know that this problem is solvable from outside, by using appropriate methods of given languages (calling free, Dispose, or by removing all references to instance).

My idea is that I create an instance, and in the constructor , I start the private timer. When the timer ends it will call some instance method and destroy the variable.

I think that in C# it should be possible to call Dispose on self, when the IDisposable is implemented, but this would not destroy the instace.

In C++ I could call the destructor, but that would lead to the memory leak, plus it is really bad practice.

In Java I have no clue, assigning to this it's not possible as it is final field.

So is there any way for instance, to destroy self?

Venkat
  • 2,549
  • 2
  • 28
  • 61
jnovacho
  • 2,825
  • 6
  • 27
  • 44
  • in C# i think is enought to point instance to null – Sebastian 506563 Jul 05 '13 at 10:28
  • Normally the GC in .NET does a pretty good job on its own. Unless you create your _own_ memory leak by keeping an object around statically (or otherwise) then it should be removed eventually. Plausibly, you could use a factory method which wouldn't return a direct reference to the object, but a weak reference instead. It probably still doesn't help much; you can still retrieve a strong reference via the weak reference. Maybe the better question is: what problem is it that you are trying to solve? – Chris Sinclair Jul 05 '13 at 10:31
  • 1
    It depends what you mean by "destroy/delete" in Java. You can call any method on `this` - that is equivalent to e.g. calling Dispose() on an object in C#. If you mean that you want the object to be garbage collected you just have to clear all references to it and wait for the garbage collector to free it. – Alex MDC Jul 05 '13 at 10:32
  • In your scenario, what should happen to any thread that is currently running an instance method of the dying instance? – Rob Jul 05 '13 at 10:39

8 Answers8

11

Your question is very interesting, and I don't know of any other way to do so in C# but to force from the inside of the instance its destruction from the outside. So this is what I came up with to check if it is possible. You can create the class Foo, which has event that is fired when the specific interval of the timer elapses. The class that is registered to that event (Bar) within event de-registers the event and sets the reference of the instance to null. This is how I would do it, tested and it works.

public class Foo
{
    public delegate void SelfDestroyer(object sender, EventArgs ea);

    public event SelfDestroyer DestroyMe;

    Timer t;

    public Foo()
    {
        t = new Timer();
        t.Interval = 2000;
        t.Tick += t_Tick;
        t.Start();
    }

    void t_Tick(object sender, EventArgs e)
    {
        OnDestroyMe();
    }

    public void OnDestroyMe()
    {
        SelfDestroyer temp = DestroyMe;
        if (temp != null)
        {
            temp(this, new EventArgs());
        }
    }
}

public class Bar
{
    Foo foo;
    public Bar()
    {
        foo = new Foo();
        foo.DestroyMe += foo_DestroyMe;
    }

    void foo_DestroyMe(object sender, EventArgs ea)
    {
        foo.DestroyMe -= foo_DestroyMe;
        foo = null;
    }
}

And in order to test this, you can set up a button click within a Form, something like this, and check it in the debugger:

Bar bar = null;
private void button2_Click(object sender, EventArgs e)
{
       if(bar==null)
             bar = new Bar();
}

So next time when you click the button, you will be able to see that Bar instance still exists but the Foo instance within it is null although it has been created within the Bar's constructor.

Nikola Davidovic
  • 8,556
  • 1
  • 27
  • 33
3

C++: If an object was allocated dynamically, it can delete its this pointer in its own function, provided the this pointer is never used again after that point.

Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
2

No, there is no way to achieve what you are trying to do in C#.

If you consider an example :

public class Kamikadze {

     ......             
     private void TimerTick(..) 
     {
        ....
        if(itsTime) {
            DestroyMe();
        }
     }

     .....
}


var kamikadze = new Kamikadze ();

after a while DestroyMe() will be called that cleans internal data.

But the reference kamikadze (pointer if you wish) is still valid and points to that memory location, so GC will not do anything, will not collect it, and instance of Kamikadze will remain in memory.

Tigran
  • 61,654
  • 8
  • 86
  • 123
1

For C++ take a look at this: http://www.parashift.com/c++-faq/delete-this.html .

Slava
  • 1,528
  • 1
  • 15
  • 23
1

The closest thing in C# that I can think of:

On creation, every object stores a reference to itself in the GC root, e.g. by putting the reference into a class static list. Outside of the class, nobody is allowed to store (strong) references to the object. Everybody uses a WeakReference and checks if the Target is still IsAlive before touching the object. That way, the only thing that is keeping the object alive is the static reference.

When the object decides to kill itself, it simply removes the reference from the list. Sooner or later, the GC collects the object. Or, if you are really impatient, call GC.Collect() (ouch!).

But I really really would not recommend this solution!

It's much better put some flag into the class/object to signal whether it's still alive and make everybody check this flag before using the object. This can be combined with the IDisposable solution.

Sebastian Negraszus
  • 11,915
  • 7
  • 43
  • 70
0

In C++, instances committing suicide are an integral part of the Finite State Machine Pattern:

//Context class contains a pointer to a State object.

void BattleshipGame::SetGameState(IState* state) {
    game_state = state;
}

void BattleshipGame::Loss() {
    game_state->Loss(this);
}

void BattleshipGame::Idle() {
    game_state->Idle(this);
}

void BattleshipGame::FlyBy() {
    game_state->FlyBy(this);
}

void BattleshipGame::Attack() {
    game_state->Attack(this);
}

void BattleshipGame::Win() {
    game_state->Win(this);
}

void BattleshipGame::Load() {
    game_state->Loading(this);
}

//State base class contains methods for switching to every state.
class IState {
public:
    virtual void Loading(BattleshipGame* context);
    virtual void Idle(BattleshipGame* context);
    virtual void FlyBy(BattleshipGame* context);
    virtual void Attack(BattleshipGame* context);
    virtual void Win(BattleshipGame* context);
    virtual void Loss(BattleshipGame* context);
protected:
private:

};

//Implementations in the State base class are defined, but empty.

//Derived States only call what they need:

void StateIdle::Loss(BattleshipGame* context) {
    //context->SetGameState(new StateLoss());
    context->SetGameState(new StateLoss(context));
    delete this;
}

void StateIdle::Idle(BattleshipGame* context) {
    context->SetGameState(new StateIdle());
    delete this;
}

void StateIdle::FlyBy(BattleshipGame* context) {
    context->SetGameState(new StateFlyBy());
    delete this;
}

void StateIdle::Win(BattleshipGame* context) {
    context->SetGameState(new StateWin());
    delete this;
}

//Similar design for all other states...
Casey
  • 10,297
  • 11
  • 59
  • 88
0

In C#, you're right you can implement IDisposable but the trick is instead of calling Dispose method make use of the using statement.

class Program
{
    static void Main(string[] args)
    {
        using (MyClass obj = new MyClass())
        {
            obj.SayHello();
        }

        // obj.SayHello(); // Error: The name 'obj' does not exist in the current context
    }
}

class MyClass : IDisposable
{
    public void SayHello()
    {
        Console.WriteLine("Hello");
    }

    public void Dispose()
    {
        // Do something (e.g: close some open connection, etc)
    }
}

For Reference: microsoft-docs/using-statement

Mark
  • 780
  • 1
  • 6
  • 17
0

I recommend using NFTLKEY. You can easily get it from the Nuget package. Best of all, it's open source: github project

Easier to understand than the examples here

Ole Pannier
  • 3,208
  • 9
  • 22
  • 33
Emin Niftiyev
  • 197
  • 1
  • 13