+4  A: 

Try this:

IDisposable d = (IDisposable)_Baz;
DisposeObject(ref d);

Edit: As Adam points out, your code doesn't require this to be ref. Objects are always passed as references.

Jon B
That doesn't work actually. You get an error that "the ref or out argument must be an assignable variable".
Noldorin
Edited per Noldorin's comment.
Jon B
Yeah, that should do the trick now. Though I still don't think there's any reason for the OP to use ref parameters here.
Noldorin
No, there isn't. It just adds needless complexity.
Adam Robinson
@dance2die, no, VARIABLES are passed by value. However, this variable holds a REFERENCE type, so the reference itself (not the content of the object) is what's being passed by value. This is similar to your other thread in that regard. The only functional difference that the ref keyword gives you is the ability to assign a value to that variable and have it reflected in the calling code. You aren't doing that, so the ref keyword is unneeded.
Adam Robinson
@dance2die - that link is broken, but that isn't right. Objects are by ref and primitives are by value.
Jon B
@Jon B: Objects references are passed by value. Objects are not passed by [ref] by default: you cannot assign a new object reference to an actual parameter and see that value after the call in the calling function.
Brian Ensink
@Jon B: SO is recognizing " as part of URL. let me repost it.
Sung Meister
@Jon B: As far as I have read on http://www.yoda.arachsys.com/csharp/parameters.html (by Jon Skeet), objects are passed by "value" by default
Sung Meister
@danc2die: Brian is absolutely correct. The *reference* is passed by value by default. The object itself isn't passed at all. I don't believe my article claims that they are... I certainly hope it doesn't say that.
Jon Skeet
Yes, the refernce is passed by value. It's a little mind bending when you think of it that way. But it's a reference - that's the important part. You're not passing the object, but a reference to it. Hence, you don't use the ref keyword.
Jon B
Clarified the by ref statement in my answer.
Jon B
@Jon B: Unless you want to change the value of the caller's variable, in which case passing the argument by reference makes perfect sense. Claiming that "objects are by ref" confuses the two issues IMO. It's much simpler and more accurate to just understand that the value of a reference type variable is a reference, not an object. At that point, it's all nice and consistent. The "objects are by ref" explanation gets really muddy when the parameter is by ref *as well*.
Jon Skeet
@Jon: While your code does compile, it violates the spirit of dance's original intent (which, admittedly, doesn't seem possible) by only assigning your temporary variable not null, not the original instance variable.
Adam Robinson
+2  A: 

This approach smells funny but I'll ignore that for now.

To fix your problem, you need to cast the objects you are passing with "(IDisposable)"

I concede to the will of the compiler, and Jon Skeet. You need an actual object for this:

IDisposable _BazD = (IDisposable)_Baz;
DisposeObject(ref _BazD);

I'd also add a null check in your DisposeObject() in addition to the try/catch. The "obj==null" will be a quick and easy check when compared to expensive exception catching should this get hit multiple times for the same object. Hmm...was that there a minute ago? Nevermind.

Michael Haren
Why is it that I would have to *explictly* cast the object as "IDisposable"? Can the compiler infer that I am actually passing an object that implements IDisposable?
Sung Meister
Sure it could, but it doesn't.
Michael Haren
@Michael: The ref keyword is what's limiting that. Were the ref keyword not there it would do exactly that.
Adam Robinson
That doesn't work. You'll get error CS1510: A ref or out argument must be an assignable variable.The problem is that the method could assign *any* IDisposable value to the variable, but the caller's variable is specifically a Bar or Baz.
Jon Skeet
@Michael Haren: As Jon Skeet has pointed out, your answer generates the following error. "ref" argument is not classified as a variable
Sung Meister
Also the fact that (correct me if I'm wrong), casting creates (or at least can create) another reference value (ie, another spot in memory to hold a reference, which may or may not hold the same reference as the original object). For example, if you created an explicit conversion on your object to IDisposable that returned a reference to a new/different object (which would likely be nonsense but is possible), then you would be passing this new reference as your ref parameter, not the original variable.
Adam Robinson
thanks for the feedback. i've updated my code ref to match @Jon B. I'd delete my answer as it's now worthless, but the comments are nice so I'll leave it.
Michael Haren
+4  A: 

There is no need for you to pass by reference, as you're passing a reference type. You should remove the ref keyword from your method definition. Do this and you shouldn't have any issues, though I'm not sure how this is more effective or clearer than simply calling Dispose() (other than the fact that you don't have to cast it for explicit implementations and this does a null check for you).

Edit

Dance, while I hope the discussion that's surrounded this topic has been helpful to you, your original intent doesn't seem to be something that's doable. In order to pass something as ref, you can't pass a variable that has a type other than what the ref parameter expects (in other words, you can't pass a variable declared as a class or other interface that implements IDisposable if the ref parameter is IDisposable). Because ref parameters allow assignments to propagate back to the caller, you would open up the possibility of allowing incompatible types being stored in your variable.

Your best bet here is to assign null yourself if that's what you want. If you want to encapsulate the null check and ignoring exceptions in to the function that's fine, but ref will not work for you in this scenario no matter how you slice it, unfortunately.

Adam Robinson
I wanted to delegate "NULL" and "ObjectDisposedException" to a method instead of having to write "try..catch" for each object.
Sung Meister
I agree with you, Adam. I would guess he's doing it this way so that the object reference is nullified so that if DisposeObject is called again with the same reference, it'll exit early.
Michael Haren
Per Microsoft guidelines, calling Dispose() should never cause an ObjectDisposedException (or, more generally, repeated calls to Dispose() should never generate an error). Even so, there's no need for the ref keyword. It's only adding complexity and greater accessibility requirements. You should remove it.
Adam Robinson
@Michael: I might agree with you if the object referenced were assigned to null ;)
Adam Robinson
You might be right on the fact that, if I am just calling "Dispose()" on a method without setting _Bar or _Baz to null within "DisposeObject", I don't think I would need "ref".
Sung Meister
@dance: According to your code, that is what you're doing. Ref parameters are, in general, a "code smell". There's no real need for you to use them in this scenario.
Adam Robinson
Marked as Answer: I have decided not to set argument to null within "DisposeObject". And therefore there was no need for "ref".
Sung Meister
+2  A: 

Here's an option for your example (can't verify it against a compiler right now, but you'll get the idea):

private void DisposeObject<T>(ref T obj) where T : IDisposable
{
    // same implementation
}

To call it, use

DisposeObject<Baz>(ref _Baz);
DisposeObject<Bar>(ref _Bar);

As pointed in the other comments, the compiler error you get has its own purpose (preventing you to assign some other type of IDisposable inside your method, leading to an inconsistent state).

Dan C.
That's nifty. It compiles but since I decided not to set an argument to null, I have already selected an answer. I think I will be able to use above code for future uses. Thanks Dan C.
Sung Meister
A: 

Thank you Dan C. I don't have enough rep yet to add comments, so I have to add this as an answer. However, full credit to Dan C for this solution.

This is working code:

public override void Dispose()
{
    base.Dispose();

    DisposeOf<UserTableAdapter>(ref userAdapter);
    DisposeOf<ProductsTableAdapter>(ref productsAdapter);

    if (connection != null)
    {
        if (connection.State == ConnectionState.Open)
        {
            connection.Close();
        }
        DisposeOf<SqlConnection>(ref connection);
    }
}

private void DisposeOf<T>(ref T objectToDispose) where T : IDisposable
{
    if (objectToDispose != null)
    {
        objectToDispose.Dispose();
        objectToDispose = default(T);
    }
}
Thorin