Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Dispose and returning Disposable objects?

157 views
Skip to first unread message

Carl R

unread,
Feb 23, 2009, 2:08:51 PM2/23/09
to
I have a class that owns a dataset, adding to it during it's work.
The method using the class fetches the dataset in order to return it
as a result in a web method.

Simplified:
class A
{
Dataset m_b;
public A()
{m_b=new Dataset();}

public DoWork()
{ /* appends to dataset m_b */}

public Dataset Result
{ return m_b;}
}

Allright, since A owns a dataset, according to fxcop it should
implement IDisposable.

class A: IDisposable
{
Dataset m_b;
public A()
{m_b=new Dataset();}

public DoWork()
{ /* appends to dataset m_b */}

public Dataset Result
{ return m_b;}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (disposing)
{
m_b.Dispose();
}
}
}

If I use the class like this:

[WebMethod]
Dataset DoStuff()
{
Dataset d;

using(A a = new A())
{
a.DoWork();
d = a.Result;
}

//d is already disposed here
return d;
}

Then A would dispose the dataset resulting in d being invalid on the
last row.
Ok, so if I change A to return a copy this problem is solved right?
class A: IDisposable
{
public Dataset Result
{ return m_b.Copy();}
}


Now what happens with the dataset that I return in the webservice?
The serialized dataset is up to the retriever, but the one on my side
can hardly be disposed automatically? (only finalized)
Alternatives:

[WebMethod]
Dataset DoStuff()
{
Dataset d;

using(A a = new A())
{
a.DoWork();
d = a.Result;
}

try
{
return d;
}
finally
{
d.Dispose();
}
}

[WebMethod]
Dataset DoStuff()
{
using(Dataset d)
{

using(A a = new A())
{
a.DoWork();
d = a.Result;
}

return d;
}
}

[WebMethod]
Dataset DoStuff()
{

using(A a = new A())
{
a.DoWork();
Using(Dataset d = a.Result)
{
return d;
}
}
}

Do you find theese alternatives reasonable? I think they look rather
strange all of them.
What is the correct way?

("Dataset" can be anything IDisposable.
d can be used between retrieving it and returning it.)

Thanks!

Peter Duniho

unread,
Feb 23, 2009, 2:31:41 PM2/23/09
to
On Mon, 23 Feb 2009 11:08:51 -0800, Carl R <carl...@gmail.com> wrote:

> I have a class that owns a dataset, adding to it during it's work.
> The method using the class fetches the dataset in order to return it
> as a result in a web method.
>
> Simplified:
> class A
> {
> Dataset m_b;
> public A()
> {m_b=new Dataset();}
>
> public DoWork()
> { /* appends to dataset m_b */}
>
> public Dataset Result
> { return m_b;}
> }
>
> Allright, since A owns a dataset, according to fxcop it should
> implement IDisposable.

Why do you say that "A owns a dataset"? From the example code you've
posted, it doesn't appear to me that A owns the dataset at all.

Also, beware of FxCop giving what are essentially false-positive
warnings. At the very least, in your example you have no need of a
finalizer (and in fact didn't even post one), and so there's no need to
call GC.SuppressFinalize(). But beyond that, FxCop doesn't really have
any way to know that your class doesn't really own the DataSet instance,
and so shouldn't necessarily be disposing it.

Without seeing the actual code, or at least a better representation of it
than you've shown here so far, it's hard to know what the best alternative
would be. But it's not clear to me why you have the "DoWork()/Result"
pattern in the first place, nor why part of that pattern requires you to
store the DataSet reference in the class itself. So, my first suggestion
would be to change the design so that you don't do that. Just return the
DataSet reference from the DoWork() method itself.

> [...]


> Do you find theese alternatives reasonable? I think they look rather
> strange all of them.
> What is the correct way?

None of those are appropriate, as they all dispose the DataSet before
returning it. That's not any more useful than what you started with by
implementing IDisposable on class A.

Pete

Carl R

unread,
Feb 23, 2009, 3:07:01 PM2/23/09
to
On 23 Feb, 20:31, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com> wrote:

> On Mon, 23 Feb 2009 11:08:51 -0800, Carl R <carl....@gmail.com> wrote:
> > Allright, since A owns a dataset, according to fxcop it should
> > implement IDisposable.
>
> Why do you say that "A owns a dataset"?  From the example code you've  
> posted, it doesn't appear to me that A owns the dataset at all.

http://msdn.microsoft.com/en-us/ms182172.aspx
Well it declares it and creates it. Then it gives away the ownership
all right, but looking at fxcop it seemed that C# had a different
view, seing the class as responsible for it.

Since microsoft says...
"When to Suppress Warnings:
Do not suppress a warning from this rule. "
...I figured I'd do my best to understand how the c# language views
this.

>
> Also, beware of FxCop giving what are essentially false-positive  
> warnings.  At the very least, in your example you have no need of a  
> finalizer (and in fact didn't even post one), and so there's no need to  
> call GC.SuppressFinalize().  But beyond that, FxCop doesn't really have  
> any way to know that your class doesn't really own the DataSet instance,  
> and so shouldn't necessarily be disposing it.

Are there any authorative design guidelines for this situation? Google
didn't help before I posted here.

>
> Without seeing the actual code, or at least a better representation of it  
> than you've shown here so far, it's hard to know what the best alternative  
> would be.  But it's not clear to me why you have the "DoWork()/Result"  
> pattern in the first place, nor why part of that pattern requires you to  
> store the DataSet reference in the class itself.

It doesn't matter. One reason could be that "DoStuff" gets called
several times. It's just an example.
It could just as well be a builder etc.

>
> > [...]
> > Do you find theese alternatives reasonable? I think they look rather
> > strange all of them.
> > What is the correct way?
>
> None of those are appropriate, as they all dispose the DataSet before  
> returning it.

Then what is the correct way? ;)

Peter Duniho

unread,
Feb 23, 2009, 3:22:38 PM2/23/09
to
On Mon, 23 Feb 2009 12:07:01 -0800, Carl R <carl...@gmail.com> wrote:

> [...]
>> > Do you find theese alternatives reasonable? I think they look rather
>> > strange all of them.
>> > What is the correct way?
>>
>> None of those are appropriate, as they all dispose the DataSet before  
>> returning it.
>
> Then what is the correct way? ;)

The only answer that can be given based on what you've shown so far is
simply "don't dispose the DataSet before returning it".

The question is too vague to provide anything beyond that.

Pete

Carl R

unread,
Feb 23, 2009, 3:35:41 PM2/23/09
to
On 23 Feb, 21:22, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com> wrote:

I don't think it's vague at all.
However, regarding datasets here's some food for thought:
http://www.developerdotstar.com/community/node/247

Peter Duniho

unread,
Feb 23, 2009, 3:44:00 PM2/23/09
to
On Mon, 23 Feb 2009 12:35:41 -0800, Carl R <carl...@gmail.com> wrote:

> [...]


>> The question is too vague to provide anything beyond that.
>

> I don't think it's vague at all.

Well, for better or worse, whether _you_ think it's vague isn't all that
relevant. Unless, of course, you wish to answer the question yourself. :)

> However, regarding datasets here's some food for thought:
> http://www.developerdotstar.com/community/node/247

That blog post is at best trusting an implementation detail that should be
ignored, and at worst mischaracterizing the purpose of IDisposable and the
dispose pattern. I would not use it to provide any guidance with respect
to the question at hand.

Pete

Carl R

unread,
Feb 23, 2009, 3:51:06 PM2/23/09
to
On 23 Feb, 21:44, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com> wrote:

> On Mon, 23 Feb 2009 12:35:41 -0800, Carl R <carl....@gmail.com> wrote:
> > [...]
> >> The question is too vague to provide anything beyond that.
>
> > I don't think it's vague at all.
>
> Well, for better or worse, whether _you_ think it's vague isn't all that  
> relevant.  Unless, of course, you wish to answer the question yourself.  :)
>

Should Disposable objects be disposed?
If a Disposable object is serialized by a web service as a result of a
return statement, does it dispose the object, taking ownership of it?

Is that more concise?

Peter Duniho

unread,
Feb 23, 2009, 4:04:01 PM2/23/09
to
On Mon, 23 Feb 2009 12:51:06 -0800, Carl R <carl...@gmail.com> wrote:

> Should Disposable objects be disposed?

Yes, they should (but obviously not before you're done with them).

> If a Disposable object is serialized by a web service as a result of a
> return statement, does it dispose the object, taking ownership of it?

I don't know off the top of my head, and without a concise-but-complete
code sample demonstrating the specific issue, I don't have a practical way
to explore the question myself.

> Is that more concise?

Not only is it more concise, it's a much more specific and answerable
question. Thank you!

Pete

Carl R

unread,
Feb 23, 2009, 4:27:04 PM2/23/09
to
On 23 Feb, 22:04, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com> wrote:

> On Mon, 23 Feb 2009 12:51:06 -0800, Carl R <carl....@gmail.com> wrote:
> > Should Disposable objects be disposed?
>
> Yes, they should (but obviously not before you're done with them).
>
> > If a Disposable object is serialized by a web service as a result of a
> > return statement, does it dispose the object, taking ownership of it?
>
> I don't know off the top of my head, and without a concise-but-complete  
> code sample demonstrating the specific issue, I don't have a practical way  
> to explore the question myself.

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
using System.Diagnostics;

namespace DisposableTestService
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
/// <summary>
/// Yields:
/// Creating X
/// X has value: Hello World
/// Disposing X with value: Hello World
/// -----
/// Serialized object: <X xmlns:xsi="http://www.w3.org/2001/
XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://tempuri.org/" />
/// </summary>
/// <returns></returns>
[WebMethod]
public X HelloWorld()
{
Trace.WriteLine("Creating X");
using (X x = new X("Hello World"))
{
Trace.WriteLine("X has value: " + x.Foo);
return x;
}
}

/// <summary>
/// Creating X
/// X has value: Hello World
/// -----
/// Serialized object:
/// <X xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://
tempuri.org/">
/// <Foo>Hello World</Foo>
/// </X>
/// </summary>
/// <returns></returns>
[WebMethod]
public X HelloWorldNoDispose()
{
Trace.WriteLine("Creating X");
X x = new X("Hello World");
Trace.WriteLine("X has value: " + x.Foo);
return x;
}
}

public class X : IDisposable
{
string m_foo;

//For serialization
public X()
{ }

public X(string value)
{
m_foo = value;
}

public string Foo
{
get { return m_foo; }
set { m_foo = value; }
}

public void Dispose()
{
Trace.WriteLine("Disposing X with value: " + m_foo);
m_foo = null;
}
}
}

> > Is that more concise?
>
> Not only is it more concise, it's a much more specific and answerable  
> question.  Thank you!
>
> Pete

Given the above example, how could one go about to have a local
disposable object disposed yet returned through the web service?

Peter Duniho

unread,
Feb 23, 2009, 4:44:22 PM2/23/09
to
On Mon, 23 Feb 2009 13:27:04 -0800, Carl R <carl...@gmail.com> wrote:

> [...]


> Given the above example, how could one go about to have a local
> disposable object disposed yet returned through the web service?

I admit, I know not very much about web services at all. But your code
example appears to be incomplete. I don't see anything that would
actually cause the web service methods to be used.

Not knowing that much about web services, I don't have first-hand
knowledge of how you'd manage the object lifetime for web methods. But,
I'm sure you can't go around disposing the object before you've returned
it from the method. If the web services framework won't do it for you
(and judging from the comments in your code, it appears you've confirmed
that it won't), you need some way to detect when the object's been
successfully serialized, and dispose it after that happens.

Perhaps there's a newsgroup specific to web services -- maybe ASP.NET
would be better? -- where you're more likely to find people with specific
information about the question.

Pete

Carl R

unread,
Feb 24, 2009, 3:19:18 AM2/24/09
to
On 23 Feb, 22:44, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com> wrote:

> On Mon, 23 Feb 2009 13:27:04 -0800, Carl R <carl....@gmail.com> wrote:
> > [...]
> > Given the above example, how could one go about to have a local
> > disposable object disposed yet returned through the web service?
>
> I admit, I know not very much about web services at all.  But your code  
> example appears to be incomplete.  I don't see anything that would  
> actually cause the web service methods to be used.

By setting up a web service project and adding this service to it, you
can call it locally from debug mode, on the description web page that
is spawned by default when you start debugging.

>
> Not knowing that much about web services, I don't have first-hand  
> knowledge of how you'd manage the object lifetime for web methods.  But,  
> I'm sure you can't go around disposing the object before you've returned  
> it from the method.  If the web services framework won't do it for you  
> (and judging from the comments in your code, it appears you've confirmed  
> that it won't), you need some way to detect when the object's been  
> successfully serialized, and dispose it after that happens.
>
> Perhaps there's a newsgroup specific to web services -- maybe ASP.NET  
> would be better? -- where you're more likely to find people with specific  
> information about the question.
>
> Pete

I have a solution. Thank you for making me writing a spike and
confirming the problem.
I think an explanation is that a web service couldn't know wether it
gets an object that it should take ownership on or if it's an object
that I want to keep, serverside.
Thus it occured to me that I should look for events or similar after
the method is returned. Webservice has a dispose that could be
overridden so that is what I did.
I have a list of disposable objects, adding to it as necessary. When
disposing the service I dispose all objects in the list.
For reference, here's the complete code.

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
using System.Diagnostics;

namespace DisposableTestService
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{

List<IDisposable> m_disposables;

public Service1()
{
m_disposables = new List<IDisposable>();
}

/// Added X to disposables. Disposable item count: 1
/// Disposing an item.


/// Disposing X with value: Hello World
/// -----

/// <X xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://
tempuri.org/">
/// <Foo>Hello World</Foo>
/// </X>
/// </summary>
/// <returns></returns>
[WebMethod]

public X HelloWorldDisposeByServiceDispose()


{
Trace.WriteLine("Creating X");
X x = new X("Hello World");
Trace.WriteLine("X has value: " + x.Foo);

m_disposables.Add(x);
Trace.WriteLine("Added X to disposables. Disposable item
count: " + m_disposables.Count);
return x;
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (null != m_disposables)
{
foreach (IDisposable d in m_disposables)
{
Trace.WriteLine("Disposing an item.");
d.Dispose();
}
m_disposables.Clear();
m_disposables = null; //Do or don't?
}
}

base.Dispose(disposing);

Peter Duniho

unread,
Feb 24, 2009, 4:35:40 AM2/24/09
to
On Tue, 24 Feb 2009 00:19:18 -0800, Carl R <carl...@gmail.com> wrote:

> [...]


> I have a solution. Thank you for making me writing a spike and
> confirming the problem.

You're welcome. :) Sometimes all a person needs is to be forced to
explain their question as though they're speaking to a moron, for a
solution to finally become apparent. :)

> I think an explanation is that a web service couldn't know wether it
> gets an object that it should take ownership on or if it's an object
> that I want to keep, serverside.

That may well be how the .NET implementation is. It's unfortunate that
Microsoft hasn't provided a way for that to happen though. For example,
it could have provided a property on the [WebMethod] attribute that
indicates whether ownership of the returned object is being passed to .NET
or not.

Alternatively, it could provide some kind of event that's raised when .NET
is done with objects automatically serialized because of the [WebMethod]
attribute, so your own code can make a decision about what to do with it
at that point. It's still not clear to me whether the call to Dispose()
provides exactly that information or not. See below...

> Thus it occured to me that I should look for events or similar after
> the method is returned. Webservice has a dispose that could be
> overridden so that is what I did.
> I have a list of disposable objects, adding to it as necessary. When
> disposing the service I dispose all objects in the list.

What's the lifetime of an instance of a WebService? I saw that the class
implements IDisposable, but not knowing much about web services, I was
concerned that these objects could live for a very long time. Perhaps
longer than if you simply wrote a finalizer for the object and let the GC
clean them up (which is normally not a good approach, but if the only
alternative is intentionally pack-ratting, maybe it's better than that :)
). I certainly didn't feel qualified to suggest that as an solution. :)

Does a single WebService instance handle multiple clients? Or does a new
one get allocated for each client session? And if so, is there in fact
some mechanism that times out the session so that you have some reasonable
assurance your objects will get cleaned up in a timely manner? Or is a
whole new instance created for each call to the [WebMethod], providing a
precise one-to-one correlation between the method call and the subsequent
call to Dispose()?

Pete

Carl R

unread,
Feb 24, 2009, 5:04:48 AM2/24/09
to
On 24 Feb, 10:35, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com> wrote:

Dispose is called immediately. A webservice afaik works like a webpage
in that it is created and destroyed for each httprequest.

Thanks!

0 new messages