I started to use Rhino-Mocks and Unit-Tests a few days ago so I'm new in this.
I created a disposable class like this:
public class SomeClass : IDisposable
{
private bool _disposed;
public SomeOtherClass ObjB { get; private set; }
public SomeClass(SomeOtherClass b)
{
ObjB = b;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
// set all properties to null
ObjB = null;
// ...
}
_disposed = true;
}
}
and the unit test which should check if the dispose was done correctly:
[TestFixture]
public class SomeClassTests
{
[Test]
public void ShouldDisposeCorrectly()
{
var classB = MockRepository.GenerateStrictMock<SomeOtherClass>()
SomeClass smth;
using (smth = MockRepository.GenerateStrictMock<SomeClass>(classB))
{ }
smth.Expect(p => p.ObjB).Should().BeNull();
}
}
Now when I start the test it throws the following error:
Rhino.Mocks.Exceptions.ExpectationViolationException : SomeClass.Dispose(True); Expected #0, Actual #1.
Can you help me to find the missing step? :-)
What are you actually wanting to test here?
That the compiler produces the correct code when you use a using statement? Seems fairly pointeless.
Or that your class implements IDisposable? You could do that with a simpler test.
Or that your disposal routine correctly disposes of the resources? This test doesn't check that. You could completely empty the Dispose(bool) method and the test you say you want to write would still pass.
Better to check that ObjB is null after the object has been disposed and that any other things which should be done in the dispose method have been. What you want to check is that the behaviour when you dispose your object is what you expect
Related
I have inherited a kind of ancient website project in c#. It originates from 2003
This has all over the place simple classes defined that inherit from IDisposible and implement a Dispose() method where GC.Collect() is called as below:
public class ProjectAutostart : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.Collect();
}
protected virtual void Dispose(bool disposing) { }
private Int32 _id;
private Int32 _stepid;
private Int64 _stepcounter;
public Int32 ID
{
set { _id = value; }
get { return _id; }
}
public Int32 StepID
{
set { _stepid = value; }
get { return _stepid; }
}
public Int64 StepCounter
{
set { _stepcounter = value; }
get { return _stepcounter; }
}
}
These classes are called like:
List<Projects.ProjectAutostart> ProjectList = DataLayer.Projects.getProjectAutoStart();
Which ends up in:
public static List<Projects.ProjectAutostart> getProjectAutoStart()
{
List<Projects.ProjectAutostart> Projects = new List<Projects.ProjectAutostart>();
DataTable DataTable = SQL.DataTable("getProjectAutoStart", null);
foreach (DataRow dt in DataTable.Rows)
{
Projects.Add(new ProjectAutostart { ID = Convert.ToInt32(dt["projectid"]), StepID = Convert.ToInt32(dt["stepid"]), StepCounter = Convert.ToInt32(e["autostartstepcounter"]) });
}
DataTable.Dispose();
return Projects;
}
I'm not experienced with this type of projects, I'm totally into the .net core restfull area so this code is strange to me.
Asides from the total weird way of implementing, These GC.Collect() and that Dispose() feel totally useless since it is managed code and it are simple class without any coding executing. Why would someone put that Dispose and GC.Collect() in there?
Should I just remove it?
As already noted in the comments, GC.Collect() in the Dispose method is completely superfluous here. Maybe they got the dispose pattern wrong in the first place.
The recommended implementation for the dispose pattern is as follows:
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); // sic!
}
protected virtual void Dispose(bool disposing)
{
}
However, since your ProjectAutostart class is a pure DTO and does not have any disposable fields (and any derived classes probably don't, either), you don't even need to implement dispose here. Just remove both Dispose methods as well as the interface declaration. What you do need to dispose is the DataTable object, but that's properly done already.
I have this class:
public abstract class ImplementsIDisposable : IDisposable
{
public abstract void Dispose();
private class InnerClass : ImplementsIDisposable
{
private bool disposedValue;
public override void Dispose()
{
if (!disposedValue)
{
doSomething();
disposedValue = true;
}
GC.SuppressFinalize(this);
}
}
}
And Code Analysis is throwing this message:
CA1063 Modify Dispose() so that it calls Dispose(true), then calls
GC.SuppressFinalize on the current object instance and then returns.
And this one:
CA1063 Ensure that Dispose() is declared as public and sealed.
Both in the this line:
public abstract void Dispose();
Can it be that it wants Dispose() to be implemented in ImplementsIDisposable instead of InnerClass?
There is no reason why public Dispose() should be virtual and much less abstract.
You need to check out the dispose pattern and implement it correctly. The warnings are hinting how you should do it but they can be rather cryptic unless you know how the pattern goes to begin with.
You can read about the Dispose Pattern here, it’s rather simple.
And of course, don’t miss this canonical SO answer on the subject.
I tried to follow the accepted answer, but I kept running into a wall because the last two lines of my method were indeed Dispose(true) and GC.SupressFinalize(this). It turns out that the warning did not make me understand that these should be the ONLY lines in the method, leaving something like the below. I believe the first link in the accepted answer actually does explain this difference, but I didn't read it as carefully as maybe I should have.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
// call Dispose on all your disposable fields/properties
}
}
finally
{
// free all unmanaged resources here. Note that this is not in an else block.
}
}
Credit to https://netvignettes.wordpress.com/2011/06/29/how-to-implement-dispose-properly/ for getting me on track.
I've got a class with one IDisposable member variable initialized in-line, and another IDisposable in the constructor.
Will Dispose() be called if the constructor throws? If so, then I presume the null check is necessary...? If not, then how does the in-line member get disposed?
sealed class SomeDisposable : IDisposable { ... }
sealed class Foo : IDisposable
{
readonly SomeDisposable sd1= new SomeDisposable(); // this doesn't throw
readonly SomeDisposable sd2;
public Foo()
{
sd2 = new SomeDisposable(); // assume this throws
// how does sd1 get Dispose()d?
}
public void Dispose()
{
sd1.Dispose();
if (sd2!= null) // is this null check necessary?
sd2.Dispose();
}
}
There is at present no way in C# to safely initialize an IDisposable with an in-line initializer except through a nasty hack involving ThreadStatic variables. The constructor must be called via factory method that creates a disposal-manager object and stores a reference in a thread-static field. Field initializers can then wrap their value in a call to a static method which will add them to the disposal-manager object.
The actual field-initializer syntax ends up being pretty reasonable:
DisposalManager Cleaner = DisposalManager.CurrentManager;
DType1 DField1 = DisposalManager.Guard(new DType1);
DType2 DField2 = DisposalManager.Guard(new DType2);
so does the Dispose cleanup:
void Dispose(bool disposing)
{
Cleaner.Cleanup(disposing);
}
Unfortunately, the needs to have every single call to Guard do its own access to the thread-static field, and to have all constructor calls wrapped in factory methods, makes the construct rather ugly. Too bad, since being able to use a single line to declare, create, and clean up a field is much nicer than having to do those things at three separate places in the code.
Lets assume you're using the following code in the form:
var foo = new Foo(someByteArray);
And your constructor throws an exception, then foo will be null, because the class constructor didn't complete. Any attempt to call it's Dispose will cause a NRE to occur.
Interesting question.
Tried this:
try
{
//caller
using (var x = new Disposable1()) { }
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
public class Disposable1 : IDisposable
{
private Disposable2 first = new Disposable2();
private Disposable2 second;
public Disposable1()
{
second = new Disposable2("Goodbye!");
}
public void Dispose()
{
Debug.WriteLine("Disposable1.Dispose()");
first.Dispose();
if (second != null)
second.Dispose();
}
}
public class Disposable2 : IDisposable
{
public string Whatever { get; set; }
public Disposable2() { Whatever = "Hello!"; }
public Disposable2(string whatever)
{
Whatever = whatever;
throw new Exception("Doh!");
}
public void Dispose()
{
Debug.WriteLine("Disposable2.Dispose()" + Whatever);
}
}
...and the output was...
Doh!
So it does appear that neither member is initialized or disposed.
Suppose, I have following classes:
public class DisposableObj : IDisposable
{
public ChildObj CreateObj();
internal object GetSomething();
// ...
}
public class ChildObj
{
private DisposableObj m_provider;
public void DoSomething()
{
m_provider.GetSomething();
}
// ...
}
It's possible that at some point the disposable object will be disposed but child object will still have a reference to it.
If at this time user will call DoSomething method then child object will try to access disposed object. This is not good hence the question:
How should I properly design such classes?
UPDATE/CLARIFICATION:
I am aware of ObjectDisposedException and all. My question probably should sound like: how to properly notify user about exceptional situation and how design the classes to make maintaining them easier?
While that is a scenario that is technically possible, this should be an exceptional state in your progam - I can't imagine why you would deliberately set up for this scenario.
Having said, that make it clear in your design who is responsible to dispose DisposableObj and when - if any child accesses the disposed object afterwards you can argue that this should cause an exception - don't work around this but throw an exception an let the exception bubble up so you can fix the logic when you discover the problem.
Implementation-wise you can achieve this by just keeping a boolean that keeps track of whether DisposableObj is disposed and on a later access just throw ObjectDisposedException. To clarify I mean the DisposableObj object itself should keep track of its state and throw ObjectDisposedException on any method call on it after it was disposed.
First thougth that comes to mind:
Provide your ChildObj class with an internal boolean property called ProviderDisposed.
Set this property to true from Dispose in your DisposableObj
However you should keep a list of the objects created to comunicate to each one the disposed state of your main object.
List<ChildObj> childsCreated = new List<ChildObj>();
public ChildObj CreateObj()
{
ChildObj obj = new ChildObj();
childsCreated.Add(obj);
return obj;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
if(disposing)
{
foreach(ChildObj obj in childsCreated)
obj.ProviderDisposed = true;
childsCreated = null;
}
disposed = true;
}
}
public class ChildObj
{
private DisposableObj m_provider;
private bool m_providerDisposed = false;
public bool ProviderDisposed
{ set { m_providerDisposed = true; } }
public void DoSomething()
{
if(m_providerDisposed == false)
m_provider.GetSomething();
// else // as from **#BrokenGlass answer**
// throw new ObjectDisposedException();
}
// ...
}
So I'm working on my DI/IoC Container OpenNETCF.IoC and I've got a (reasonable) feature request to add some form of lifecycle management for IDisposable items in the container collections.
My current thinking is that, since I can't query an object to see if it's been disposed, and I can't get an event for when it's been disposed, that I have to create some form of wrapper for objects that a developer wants the framework to manage.
Right now objects can be added with AddNew (for simplicity sake we'll assume there's only one overload and there is no Add):
public TTypeToBuild AddNew<TTypeToBuild>() { ... }
What I'm considering is adding a new method (well group of them, but you get the picture):
public DisposableWrappedObject<IDisposable> AddNewDisposable<TTypeToBuild>()
where TTypeToBuild : class, IDisposable
{
...
}
Where the DisposableWrappedObject looks like this:
public class DisposableWrappedObject<T>
where T : class, IDisposable
{
public bool Disposed { get; private set; }
public T Instance { get; private set; }
internal event EventHandler<GenericEventArgs<IDisposable>> Disposing;
internal DisposableWrappedObject(T disposableObject)
{
if (disposableObject == null) throw new ArgumentNullException();
Instance = disposableObject;
}
~DisposableWrappedObject()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
lock(this)
{
if(Disposed) return;
EventHandler<GenericEventArgs<IDisposable>> handler = Disposing;
if(handler != null)
{
Disposing(this, new GenericEventArgs<IDisposable>(Instance));
}
Instance.Dispose();
Disposed = true;
}
}
}
Now, when an items gets added to the container via AddNewDIsposable, an eventhandler is also added so that when it gets Disposed (via the wrapper) the framework removes it from the underlying collection.
I actually have this implemented and it's passing the unit tests, but I'm looking for opinions on where this might be broken, or how it might be made more "friendly" to the consuming developer.
EDIT 1
Since there was a question on how the Disposing event is used, here's some code (trimmed to what's important):
private object AddNew(Type typeToBuild, string id, bool wrapDisposables)
{
....
object instance = ObjectFactory.CreateObject(typeToBuild, m_root);
if ((wrapDisposables) && (instance is IDisposable))
{
DisposableWrappedObject<IDisposable> dispInstance = new
DisposableWrappedObject<IDisposable>(instance as IDisposable);
dispInstance.Disposing += new
EventHandler<GenericEventArgs<IDisposable>>(DisposableItemHandler);
Add(dispInstance as TItem, id, expectNullId);
instance = dispInstance;
}
....
return instance;
}
private void DisposableItemHandler(object sender, GenericEventArgs<IDisposable> e)
{
var key = m_items.FirstOrDefault(i => i.Value == sender).Key;
if(key == null) return;
m_items.Remove(key);
}
Maybe I'm missing something, but why add new methods to the API? When an object is added to the container, you could as-cast to check if it's IDisposable and handle it appropriately if so.
I'm also wondering if you need the destructor. Presuming the container is IDisposable (like Unity's), you could just implement the Basic Dispose Pattern and save a lot of GC overhead.
Some questions that may be applicable:
How do you reconcile IDisposable and IoC?
Can inversion of control and RAII play together?