Seeking best inputs on correct usage of C# using statement. Can I use using statement on a parameter object as in the following uncommon example code snippet (viz., multi-layer application)?
Although the code snippet is different from what I feel that the using statement should be in ProcessFileAndReturnNumberFromStream() method of 'Business' class.
Why is it an uncommon practice to use using statement on object passed via parameter? Please correct or elaborate on the flaw?
using System;
using System.IO;
class Data
{
public double? GetNumberFromStream(StreamReader sr)
{
double? number;
try
{
using (sr)
{
number = Convert.ToDouble(sr.ReadToEnd());
return number;
}
}
finally
{
number = null;
}
}
}
class Business
{
public double? ProcessFileAndReturnNumberFromStream()
{
string fileName = "Test.txt";
StreamReader sr = new StreamReader(fileName);
Data dat = new Data();
return dat.GetNumberFromStream(sr);
}
}
class GUI
{
static void Main()
{
Business bus = new Business();
double? number = bus.ProcessFileAndReturnNumberFromStream();
Console.WriteLine(number);
Console.ReadKey();
}
}
Please help.
Thanks
If a method is passed an object that implements IDisposable, it's usually the responsibility of the caller to manage the lifetime of that object, rather than the callee.
public double? ProcessFileAndReturnNumberFromStream()
{
string fileName = "Test.txt";
Data dat = new Data();
using (StreamReader sr = new StreamReader(fileName))
{
return dat.GetNumberFromStream(sr);
}
}
The caller that is passing the instance of IDisposable should be the one to use the using statement. If the callee uses it, the object will be disposed while outside the immediate control of the caller who 'owns' the object.
Can I use using statement on a parameter object as in the following uncommon example code snippet (viz., multi-layer application)?
You can, but it's generally odd to do so. Usually whatever is creating the StreamReader would be expecting to "own" it and dispose of it when they're done with it. It would be more usual for your ProcessFileAndReturnNumberFromStream method to be:
using (StreamReader sr = new StreamReader(fileName))
{
Data dat = new Data();
return dat.GetNumberFromStream(sr);
}
(Although I'd personally use File.OpenText instead of explicitly constructing the StreamReader.)
Your GetNumberFromStream method would then not need the using statement. It also doesn't need the try/finally block at all - it's an odd implementation all round, given that it will never return null, either...
It's also odd that you're creating a new instance of Data and then doing nothing with it - as your GetNumberFromStream method doesn't use an instance variables or override a base class method, you should consider making it static.
Such API would be extremely troublesome.
You would never know whether or not the object passed to a method is disposed inside the method or not. Thus, if this is you who create the object and pass it there, you would also never know whether or not you should dispose the object you have just created and passed to the method or not.
I guess then, while this is technically possible, it would promote the bad programming style.
Related
I noticed the following object disposal code pattern in a C# project and I was wondering if it's acceptable (although it works).
public object GetData()
{
object obj;
try
{
obj = new Object();
// code to populate SortedList
return obj;
}
catch
{
return null;
}
finally
{
if (obj != null)
{
obj.Dispose();
obj = null;
}
}
}
For this example, I'm using a general 'object' instead of the actual IDisposable class in the project.
I know that the 'finally' block will be executed every time, even when the value is returned, but would it affect the return value (or would it be a new object instance) in any way since the object is being set to null (for what seems like object disposal and GC purposes).
Update 1:
I tried the following snippet and the return object is non-null, although the local object is set to null, so it works, which is a bit strange considering some of the comments below:
public StringBuilder TestDate()
{
StringBuilder sb;
try
{
sb = new StringBuilder();
sb.Append(DateTime.UtcNow.ToString());
return sb;
}
catch
{
return null;
}
finally
{
sb = null;
}
}
Btw, I'm using C# 4.0.
P.S. I'm just reviewing this project code. I'm not the original author.
Update 2:
Found the answer to this mystery [1]. The finally statement is executed, but the return value isn't affected (if set/reset in the finally block).
[1] What really happens in a try { return x; } finally { x = null; } statement?
This code will compile fine (assuming that you are not actually using an Object but something that implements IDisposable), but it probably won't do what you want it to do. In C#, you don't get a new object without a new; this code will return a reference to an object that has already been disposed, and depending on the object and what Dispose() actually does, trying to use a disposed object may or may not crash your program.
I assume the idea is to create an object, do some stuff with it, then return the object if successful or null (and dispose the object) on failure. If so, what you should do is:
try {
obj = new MyClass();
// ... do some stuff with obj
return obj;
}
catch {
if(obj != null) obj.Dispose();
return null;
}
Simply using the using statement achieves the same result as that, and is the standard practice
public int A()
{
using(IDisposable obj = new MyClass())
{
//...
return something;
}
}
I would, however, advise against returning your IDisposable object.
When you dispose of an object, it is supposed to be considered "unusable". And so, why return it?
If the object's lifetime needs to be longer than the method A's lifetime, consider having the calling method B instantiate the object, and pass it as a parameter to method A.
In this case, method Bwould be the one using the using statement, inside which it would call A.
If you are returning an IDisposable object, then it is the responsibility of your caller to dispose of it:
public IDisposable MakeDisposableObject()
{
return new SqlConnection(""); // or whatever
}
caller:
using (var obj = MakeDisposableObject())
{
}
It makes less than no sense for your method to dispose of an object and then return it. The disposed object will be of no value to the caller. In general, referencing a disposable object which has been disposed should produce an ObjectDisposedException.
A few observations.
That code wouldn't compile because object doesn't have a .Dispose() method.
Why wouldn't you use IDisposable?
Why would you dispose of an object that is being returned, since returning you would return an object for the purpose of some other code to use it. The concept of "disposing" of something is to give it a chance to clean up after itself and its used, un-managed resources. If you are returning an object that is supposed to be used elsewhere, but has unmanaged resources that you want to clean up before the object gets used anywhere else, then you shuld really have 2 separate objects. One to load some data that would be disposable, and another object that would contain the usable loaded content that you want to pass around. An example of this would be something like stream readers in the .NET framework. You would normally new a stream reader, read it into a byte[] or some other data object, .Dispose() the stream reader, then return the byte[]. The "loader" that has some resources to dispose of in a timely fashion is separate from the object containing the "loaded" data that can be used without needing to be disposed.
I am trying to serialse a fingerprint FMD to XML using the code below, but get an error:
Error: DPUruNet.DataResult`1[DPUruNet.Fmd] cannot be serialized
because it does not have a parameterless constructor.
public void storePrint(DataResult<Fmd> resultConversion)
{
//store fingerprint as byte and insert to server------------
using (StreamWriter myWriter = new StreamWriter("test.txt", false))
{
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(resultConversion.GetType());
x.Serialize(myWriter, resultConversion);
}
MessageBox.Show("Fingerprint Stored!");
//------------------------------------------------------------
}
private void OnCaptured(CaptureResult captureResult)
{
try
{
// Check capture quality and throw an error if bad.
if (!_sender.CheckCaptureResult(captureResult)) return;
count++;
DataResult<Fmd> resultConversion = FeatureExtraction.CreateFmdFromFid(captureResult.Data, Constants.Formats.Fmd.ANSI);
SendMessage(Action.SendMessage, "A finger was captured. \r\nCount: " + (count));
if (resultConversion.ResultCode != Constants.ResultCode.DP_SUCCESS)
{
_sender.Reset = true;
throw new Exception(resultConversion.ResultCode.ToString());
}
preenrollmentFmds.Add(resultConversion.Data);
//--------------------CALL METHOD
storePrint(resultConversion);
//
The class DataResult is being referenced, so I can not alter it
UPDATE
If you don't have access to the DataResult<T> class, then you might have to take a slightly different approach and wrap this class with a different, serializable one. You can find a full example here:
How can I XML Serialize a Sealed Class with No Parameterless Constructor?
Previous Answer
The error is clear; you just need to add a parameterless constructor to the DataResult<T> class:
public class DataResult<T>
{
// Add a default constructor (public visibility, no parameters)
public DataResult()
{
// You can still define a method body if you wish,
// no restrictions there. Just don't do anything that
// could jeopardize the (de)serialization.
}
}
As for the implications of adding a default constructor, without knowing what
FeatureExtraction.CreateFmdFromFid(...)
is doing to create the DataResult<Fmd>, it would be impossible to know whether it would cause any issues.
Thanks to Cory, that is a useful answer, however in this example there is another way of serializing using
tempFingerPrint = Fmd.SerializeXml(resultConversion.Data);
this is specific to the Digital Persona SDK
Here's the scenario:
I have a method that reads in a file via a FileStream and a StreamReader in .NET. I would like to unit test this method and somehow remove the dependency on the StreamReader object.
Ideally I would like to be able to supply my own string of test data instead of using a real file. Right now the method makes use of the StreamReader.ReadLine method throughout. What is an approach to modifying the design I have now in order to make this test possible?
Depend on Stream and TextReader instead. Then your unit tests can use MemoryStream and StringReader. (Or load resources from inside your test assembly if necessary.)
Note how ReadLine is originally declared by TextReader, not StreamReader.
The simplest solution would be to have the method accept a Stream as a parameter instead of opening its own FileStream. Your actual code could pass in the FileStream as usual, while your test method could either use a different FileStream for test data, or a MemoryStream filled up with what you wanted to test (that wouldn't require a file).
Off the top of my head, I'd say this is a great opportunity to investigate the merits of Dependency Injection.
You might want to consider redesigning your method so that it takes a delegate that returns the file's contents. One delegate (the production one) might use the classes in System.IO, while the second one (for unit testing), returns the contents directly as a string.
I think the idea is to dependency inject the TextReader and mock it for unit testing. I think you can only mock the TextReader because it is an abstract class.
public class FileParser
{
private readonly TextReader _textReader;
public FileParser(TextReader reader)
{
_textReader = reader;
}
public List<TradeInfo> ProcessFile()
{
var rows = _textReader.ReadLine().Split(new[] { ',' }).Take(4);
return FeedMapper(rows.ToList());
}
private List<TradeInfo> FeedMapper(List<String> rows)
{
var row = rows.Take(4).ToList();
var trades = new List<TradeInfo>();
trades.Add(new TradeInfo { TradeId = row[0], FutureValue = Convert.ToInt32(row[1]), NotionalValue = Convert.ToInt32(row[3]), PresentValue = Convert.ToInt32(row[2]) });
return trades;
}
}
and then Mock using Rhino Mock
public class UnitTest1
{
[Test]
public void Test_Extract_First_Row_Mocked()
{
//Arrange
List<TradeInfo> listExpected = new List<TradeInfo>();
var tradeInfo = new TradeInfo() { TradeId = "0453", FutureValue = 2000000, PresentValue = 3000000, NotionalValue = 400000 };
listExpected.Add(tradeInfo);
var textReader = MockRepository.GenerateMock<TextReader>();
textReader.Expect(tr => tr.ReadLine()).Return("0453, 2000000, 3000000, 400000");
var fileParser = new FileParser(textReader);
var list = fileParser.ProcessFile();
listExpected.ShouldAllBeEquivalentTo(list);
}
}
BUT the question lies in the fact whether it is a good practice to pass such an object from the client code rather I feel it should be managed with using within the class responsible for processing. I agree with the idea of using a sep delegate for the actual code and one for the unit testing but again that is a bit of extra code in production. I may be a bit lost with the idea of dependency injection and mocking to even file IO open/read which actually is not a candidate for unit testing but the file processing logic is which can be tested by just passing the string content of the file (AAA23^YKL890^300000^TTRFGYUBARC).
Any ideas please! Thanks
I am returning the variable I am creating in a using statement inside the using statement (sounds funny):
public DataTable foo ()
{
using (DataTable properties = new DataTable())
{
// do something
return properties;
}
}
Will this Dispose the properties variable??
After doing this am still getting this Warning:
Warning 34 CA2000 : Microsoft.Reliability : In method 'test.test', call System.IDisposable.Dispose on object 'properties' before all references to it are out of scope.
Any Ideas?
Thanks
If you want to return it, you can't wrap it in a using statement, because once you leave the braces, it goes out of scope and gets disposed.
You will have to instantiate it like this:
public DataTable Foo()
{
DataTable properties = new DataTable();
return properties;
}
and call Dispose() on it later.
Yes, it will dispose it - and then return it. This is almost always a bad thing to do.
In fact for DataTable, Dispose almost never does anything (the exception being if it's remoted somewhere, IIRC) but it's still a generally bad idea. Normally you should regard disposed objects as being unusable.
Supposedly, this is the pattern for a factory method that creates a disposable object. But, I've still seen Code Analysis complain about this, too:
Wrapper tempWrapper = null;
Wrapper wrapper = null;
try
{
tempWrapper = new Wrapper(callback);
Initialize(tempWrapper);
wrapper = tempWrapper;
tempWrapper = null;
}
finally
{
if (tempWrapper != null)
tempWrapper.Dispose();
}
return wrapper;
This should guarantee that if the initialization fails, the object is properly disposed, but if everything succeeds, an undisposed instance is returned from the method.
MSDN Article: CA2000: Dispose objects before losing scope.
Yes. Why are you using the using keyword on something you don't want disposed at the end of the code block?
The purpose of the using keyword is to dispose of the object.
http://msdn.microsoft.com/en-us/library/yh598w02.aspx
The point of a using block is to create an artificial scope for a value/object. When the using block completes, the object is cleaned up because it is no longer needed. If you really want to return the object you are creating, than it is not a case where you want to use using.
This will work just fine.
public DataTable foo ()
{
DataTable properties = new DataTable();
// do something
return properties;
}
Your code using the using keyword expands to:
{
DataTable properties = new DataTable();
try
{
//do something
return properties;
}
finally
{
if(properties != null)
{
((IDisposable)properties).Dispose();
}
}
}
Your variable is being disposed by nature of how using works. If you want to be able to return properties, don't wrap it in a using block.
The other responses are correct: as soon as you exit the using block, your object is disposed. The using block is great for making sure that an object gets disposed in a timely manner, so if you don't want to rely on the consumers of your function to remember to dispose the object later, you can try something like this:
public void UsingDataContext (Action<DataContext> action)
{
using (DataContext ctx = new DataContext())
{
action(ctx)
}
}
This way you can say something like:
var user = GetNewUserInfo();
UsingDataContext(c => c.UserSet.Add(user));
Most of the examples of the using statement in C# declare the object inside the brackets like this:
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Customers", connection))
{
// Code goes here
}
What happens if I use the using statement in the following way with the object declared outside the using statement:
SqlCommand cmd = new SqlCommand("SELECT * FROM Customers", connection);
using (cmd)
{
// Code goes here
}
Is it a bad idea to use the using statement in the way I have in the second example and why?
Declaring the variable inside the using statement's control expression limits the scope of the variable to inside the using statement. In your second example the variable cmd can continue to be used after the using statement (when it will have been disposed).
Generally it is recommended to only use a variable for one purpose, limiting its scope allows another command with the same name later in scope (maybe in another using expression). Perhaps more importantly it tells a reader of your code (and maintenance takes more effort than initial writing) that cmd is not used beyond the using statement: your code is a little bit more understandable.
Yes, that is valid - the object will still be disposed in the same manner, ie, at the end and if execution flow tries to leave the block (return / exception).
However if you try to use it again after the using, it will have been disposed, so you cannot know if that instance is safe to continue using as dispose doesn't have to reset the object state. Also if an exception occurs during construction, it will not have hit the using block.
I'd declare and initialize the variable inside the statement to define its scope. Chances are very good you won't need it outside the scope if you are using a using anyway.
MemoryStream ms = new MemoryStream(); // Initialisation not compiled into the using.
using (ms) { }
int i = ms.ReadByte(); // Will fail on closed stream.
Below is valid, but somewhat unnecessary in most cases:
MemoryStream ms = null;
using (ms = new MemoryStream())
{ }
// Do not continue to use ms unless re-initializing.
I wrote a little code along with some unit tests. I like it when I can validate statements about the question at hand. My findings:
Whether an object is created before or in the using statement doesn't matter. It must implement IDisposable and Dispose() will be called upon leaving the using statement block (closing brace).
If the constructor throws an exception when invoked in the using statement Dispose() will not be invoked. This is reasonable as the object has not been successfully constructed when an exception is thrown in the constructor. Therefore no instance exists at that point and calling instance members (non-static members) on the object doesn't make sense. This includes Dispose().
To reproduce my findings, please refer to the source code below.
So bottom line you can - as pointed out by others - instantiate an object ahead of the using statement and then use it inside the using statement. I also agree, however, moving the construction outside the using statement leads to code that is less readable.
One more item that you may want to be aware of is the fact that some classes can throw an exception in the Dispose() implementation. Although the guideline is not to do that, even Microsoft has cases of this, e.g. as discussed here.
So here is my source code include a (lengthy) test:
public class Bar : IDisposable {
public Bar() {
DisposeCalled = false;
}
public void Blah() {
if (DisposeCalled) {
// object was disposed you shouldn't use it anymore
throw new ObjectDisposedException("Object was already disposed.");
}
}
public void Dispose() {
// give back / free up resources that were used by the Bar object
DisposeCalled = true;
}
public bool DisposeCalled { get; private set; }
}
public class ConstructorThrows : IDisposable {
public ConstructorThrows(int argument) {
throw new ArgumentException("argument");
}
public void Dispose() {
Log.Info("Constructor.Dispose() called.");
}
}
[Test]
public void Foo() {
var bar = new Bar();
using (bar) {
bar.Blah(); // ok to call
}// Upon hitting this closing brace Dispose() will be invoked on bar.
try {
bar.Blah(); // Throws ObjectDisposedException
Assert.Fail();
}
catch(ObjectDisposedException) {
// This exception is expected here
}
using (bar = new Bar()) { // can reuse the variable, though
bar.Blah(); // Fine to call as this is a second instance.
}
// The following code demonstrates that Dispose() won't be called if
// the constructor throws an exception:
using (var throws = new ConstructorThrows(35)) {
}
}
The idea behind using is to define a scope, outside of which an object or objects will be disposed.
If you declare the object you are about to use inside using in advance, there's no point to use the using statement at all.
It has been answered and the answer is: Yes, it's possible.However, from a programmers viewpoint, don't do it! It will confuse any programmer who will be working on this code and who doesn't expect such a construction. Basically, if you give the code to someone else to work on, that other person could end up being very confused if they use the "cmd" variable after the using. This becomes even worse if there's even more lines of code between the creation of the object and the "using" part.