0

Trying to see if I'm understanding this correctly. Regretfully, I have not had much experience with IDisposable. We're taking a static class and making it non-static, and it's a class that is responsible for making web service calls in our Xamarin app. This is an object that I would definitely not want lying around. So I thought of having this class inherit the IDisposable interface, and I implemented the methods as shown:

private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { // TODO: dispose managed state (managed objects). } // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. // TODO: set large fields to null. disposedValue = true; } } // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. //~WebServiceCallThread() //{ // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. // Dispose(false); //} // This code added to correctly implement the disposable pattern. public void Dispose() { // Do not change this code. Put cleanup code in Dispose(bool disposing) above. Dispose(true); // TODO: uncomment the following line if the finalizer is overridden above. //GC.SuppressFinalize(this); } 

So all this appears to be doing, is when the Dispose method is called, it then calls a virtual method declared above Dispose(bool disposing). With the current code, this does nothing (or so it seems). It just calls the Dispose method, in which that calls an overloaded Dispose method. But nothing is actually "disposing" here.

Upon some research, it SEEMS (which is why I'm asking, I think I am understanding correctly). It says to only call a finalizer and the GC.SuppressFinalize method IF you dispose managed state. I'm not sure what dispose manage state means, but there's really nothing in my class that needs to get disposed. I just have some global int variables but that's it. The meat of this class is a HttpCall, which is already disposing of the objects automatically, as such:

public async void CallUrlHttpClient(string URL, System.Action<string> Handler, System.Action<XamarinMobile.Classes.ErrorInfo> ErrorHandler, int Tries) { var result = string.Empty; didMakeSuccessfulHttpRequest = false; using (var client = new HttpClient()) { ... Code } ... 

So here's my question: Do I need to make this class inherit IDisposable? I'm wondering if anything under the hood is being done, but it seems as if my application can just utilize the GC to get rid of my object that uses this class. This is how I call it, via a static method in a class:

 public static void WebServiceCall(string URL, System.Action<string> Callback) { //using (XamarinMobile.Classes.WebServiceCallThread thread = new Classes.WebServiceCallThread()) //{ XamarinMobile.Classes.WebServiceCallThread thread = new Classes.WebServiceCallThread(); thread.Call(URL, Callback); //} } 

If I understand GC correctly, once this method is done, the GC will automatically get rid of the object. So do I really need to make the WebServiceCallThread inherit from IDisposable? Again I'm asking if I'm understanding all of this correctly. If not, please correct me and let me know where I'm confused.

Thanks.

5
  • 2
    If you don't have unmanaged resources being held by your object (in fields), and don't have managed objects that themselves implement IDisposable, also in fields, then no, you don't need to implement IDisposable. Commented May 26, 2017 at 19:54
  • @LasseV.Karlsen But am I correct in that, GC will automatically dispose it after the static method is done? If not, then maybe I should implement it? Why not free up a resource as soon as we can? Commented May 26, 2017 at 20:01
  • I sense you are thinking the GC calls Dispose? It does not. Commented May 26, 2017 at 20:04
  • The garbage collector will take care of unreferenced objects efficiently. That's its job. Commented May 26, 2017 at 20:05
  • No I did not think that, but thanks. Commented May 26, 2017 at 20:07

1 Answer 1

2

If your class created the HttpClient and maintained that instance throughout its own lifetime (like an instance variable) then you would implement IDisposable, and your Dispose() method would dispose the HttpClient.

That would be this part:

if (disposing) { // TODO: dispose managed state (managed objects). _httpClient.Dispose(); } 

In this case you don't need to implement IDisposable because you're already disposing your HttpClient.

 using (var client = new HttpClient()) { ... Code } 

However, it's actually recommended to create one instance of HttpClient per endpoint and reuse it instead of creating and disposing over and over. (If your load isn't that heavy then you likely won't see any bad effect from creating and disposing HttpClient.)

If you wanted to avoid creating and disposing HttpClient then you could implement IDisposable. Your class either creates or receives (in its constructor) an instance of HttpClient. Now that your class "owns" that instance which needs to be disposed when your class is disposed, you make your class IDisposable. That way others know that your class needs to be disposed. They might not know why, but that's not important. By making it IDisposable you're letting them know that they need to dispose it. And then when your class is disposed it cleans up its HttpClient.


Just to provide a little extra clarification:

Many people, if asked "What is IDisposable for?" will answer that it causes garbage collection. It actually has nothing to do with garbage collection. Objects always get garbage collected when they're out of scope (there are no more references to them) whether or not they implement IDisposable.

The confusion comes up because the recommended pattern for IDisposable (which you referenced) includes a finalizer (~WebServiceCallThread()) which is called when the object is garbage collected.

When the garbage collector removes an item it calls the finalizer if there is one. This pattern causes the finalizer to call Dispose() if it hasn't been called already, just as a backup in case someone didn't call Dispose() like they were supposed to. But it's no substitute for calling Dispose() because there's no telling when the garbage collector will collect the item. There's a chance the finalizer will never get called. It's just a backup to try to mitigate what happens if consumers don't call Dispose().

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.