0

I have a very interesting scenario where I would like a class to inform another entity it has been destroyed; however, its not doing what I want it too.

The Problem

The deconstructor, for some reason does not do what its supposed to do.

The Question

Why is the destructor not being invoked and make sure that it does do its necessary clean up.

The Code

So here we have the informer ~

class Connection 
{
   public const int Port = 50000;// Can be any range between 49152 and 65536

    //Teh Constructor
    public Boolean Connect()
    {
        //SetInformation
        Information.Id = 545;

        using (var WebServ = new ClientSDKSoapClient("ClientSDKSoap"))
        {
            ContinueConnection.WaitOne();
            WebServ.ClientLogin(Information);
        }
        return true;
    }

    ~Connection()
    {
        using (var WebServ = new ClientSDKSoapClient("ClientSDKSoap"))
        {
            WebServ.ClientLogout(Information);
        }
    }
}

Additional Information

I want the web service to record if the Connection Class is destroyed for any given reason. When the client is connecting, it works perfectly. The Web Service records every method called from it. If I call ClientLogout explicitly, it will work.

I am aware I can implement IDisposable; however, this object is not intended to be used within the lifetime of one method. In fact, its intended for use for the entire duration of the program and the failure of this object basically results in the failure of the entire project. (Although I suppose main IS a method...)

I need to release a network connection; however, its not in this program, its in another program and unless ClientLogout is called, it won't be released.

My Research

Microsoft says that you should use the deconstructor for the release of unmanaged resources making an explicit reference to network connections. This ones got my quite stumped.

user229044
  • 232,980
  • 40
  • 330
  • 338
Aelphaeis
  • 2,593
  • 3
  • 24
  • 42
  • Can you show the code where you allocate/initialize the object and then point out where you expect it to be GC'd? – evanmcdonnal Aug 23 '13 at 20:59
  • 7
    My suggestion is to use `IDisposable` rather than a destructor. The destructor happens whenever the garbage collector wants to get rid of it. Wrapping your object in a `using` will make it run the dispose when it leaves the using. – gunr2171 Aug 23 '13 at 21:00
  • Agreed on using `IDisposable`. http://stackoverflow.com/questions/4898733/when-should-i-create-a-destructor/4899622#4899622 – Mike Precup Aug 23 '13 at 21:03
  • 1
    You are actually using C# objects and not directly handling [unmanaged resources](http://stackoverflow.com/questions/3433197/what-exactly-are-unmanaged-resources). – François Moisan Aug 23 '13 at 21:10

2 Answers2

3

I think you should implement a Dispose pattern for your Connection class, rather than relying on an obscure deconstructor metaphor. This would be the "canonical" way to do it.

public class Connection : IDisposable  // <== Inherit from IDisposable interface
{
    public const int Port = 50000;// Can be any range between 49152 and 65536

    private SomeType webserv; // Use whatever real type is appropriate here.
    private Information information = new Information();  // or whatever

    // This is a real constructor.
    public Connection()
    {
        //SetInformation
        information.Id = 545;

        webServ = new ClientSDKSoapClient("ClientSDKSoap"))
        webserv.ContinueConnection.WaitOne();
        webServ.ClientLogin(information);
    }

    // Implement IDisposable interface
    public void Dispose()
    {
        webServ.ClientLogout(information);
    }
}

And then use it thusly

using (var connection = new Connection())
{
    // Use the connection here.
}

The client will be logged out when you leave the using block.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • Sorry I took so long to mark this correctly~ I realized that my problem was caused by a potential failure on my part in regards to designing. I've fixed it now and I think it will mark a lot more sense to future people managing my code. Thanks a lot. – Aelphaeis Aug 26 '13 at 14:14
1

Microsoft says that you should use the deconstructor for the release of unmanaged resources making an explicit reference to network connections. This ones got my quite stumped.

The docs here are misleading. It really just means you need a finalizer somewhere in your object inheritance chain, to ensure that any unmanaged resources are appropriately cleaned up. But you only need this finalizer once for the entire inheritance tree, at the level where the unmanaged resource is first allocated.

As an example, you do not need a destructor or finalizer if you build a class for a data access layer to wrap the SqlConnection type, because the core SqlConnection type already has one. What you should do, though, is implement IDisposable and write code to ensure prompt disposal, so the finalizer on your SqlConnection will be called sooner, rather than later. But if you were to build a whole new database engine that competes with Sql Server, MySql, Oracle, Access, and the like, and were implementing the ADO.Net provider for this new database engine, then would need to write a finalizer for your connection type, because none exists yet.

In this case, ClientSDKSoap type already has a destructor; you do not need to write another.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794