|
No, it's not a bug. You left it open, so it works exactly as it should.
The XmlReader class implements IDisposable, so you can use that to make sure that it's closed:
using (XmlReader rdr = XmlReader.Create(input_XML_file, settings)) {
...
}
---
b { font-weight: normal; }
|
|
|
|
|
i didn't leave anything "open", because i didn't open anything. i gave XmlReader a filename and XmlReader opened the file. XmlReader then left the file open after it threw an exception. and XmlReader left the file open even after the program exited - not me.
|
|
|
|
|
Chris Losinger wrote: i didn't leave anything "open", because i didn't open anything. i gave XmlReader a filename and XmlReader opened the file. XmlReader then left the file open after it threw an exception. and XmlReader left the file open even after the program exited - not me.
If you think like that, then you never open anything ever. You just give a filename to the File.Open method and it opens the file. You just give a connection string to the SqlConnection object, and it opens the database connection.
Just because you don't call the interrupt that opens the file yourself, doesn't free you from the responsibility to make sure that it's closed properly.
---
b { font-weight: normal; }
|
|
|
|
|
that's just silly. surely you can see the difference between a function called "File.Open" and one called "XmlReader.Create".
in one case the caller expects and gets an open file, because that's the reason for calling the function. in the other, the caller doesn't get an open File object, has no access to any open File object, and isn't expecting one - the opened file is an undocumented side-effect.
Guffa wrote: Just because you don't call the interrupt that opens the file yourself, doesn't free you from the responsibility to make sure that it's closed properly
if it's the caller's responsibility that the XmlReader user should close the file, then why does XmlReader close the file by itself in some situations but not others; and why does the MSDN fail to mention anything about this behavior, or this "responsibility" ?
at best, this function is inconsistent in behavior and poorly-documented.
|
|
|
|
|
Chris Losinger wrote: then why does XmlReader close the file by itself in some situations but not others
Because it has a finalizer which closes the file for you, but this is not deterministic - you cannot predict when this will occur.
Anything which implements IDisposable should be Dispose d by the programmer when the object has been finished with. That's the rule I follow. You can use a using block to automatically call Dispose when execution leaves the block - this includes exits due to exceptions as well as normal program execution.
Finalizers run on a single separate finalizer thread, which processes a queue of finalizable objects. An object with a finalizer gets pushed onto the end of the queue when the garbage collector runs, unless GC.SuppressFinalize has been called on the object (this is usually done by the implementation of Dispose ). The finalizer thread runs the finalizers asynchronously with respect to the rest of the program. Only when the finalizer has run can the memory that the object was occupying be freed. Best practice is to avoid having objects end up in the finalizer, to reduce the memory load and to avoid synchronization problems with finalizers.
|
|
|
|
|
I don't know if the object representing the file has a finalizer, but if it does, then I don't think XmlReader would have one. As you might be knowing, the order in which finalizers are called is undefined, so it's possible the file object gets finalized before the XmlReader instance does.
|
|
|
|
|
OK, XmlReader itself does not have a finalizer. The FileStream which is managed by the XmlReader does. The rest of my comments still apply - you have to dispose anything that's disposable.
|
|
|
|
|
Mike Dimmick wrote: The rest of my comments still apply - you have to dispose anything that's disposable.
No question about that. I totally agree.
|
|
|
|
|
Chris Losinger wrote: that's just silly. surely you can see the difference between a function called "File.Open" and one called "XmlReader.Create".
If course there are differences, but that is not really relevant. You seem to fail to see the similarities.
Chris Losinger wrote: in one case the caller expects and gets an open file, because that's the reason for calling the function. in the other, the caller doesn't get an open File object, has no access to any open File object, and isn't expecting one - the opened file is an undocumented side-effect.
You never get direct access to an open file through the framework. You access files through streams, readers and writers.
Chris Losinger wrote: if it's the caller's responsibility that the XmlReader user should close the file, then why does XmlReader close the file by itself in some situations but not others; and why does the MSDN fail to mention anything about this behavior, or this "responsibility" ?
at best, this function is inconsistent in behavior and poorly-documented.
The reader closes the file if it knows that you can't use it any more. If you don't tell it anything and just leave it hanging, it can't close the file.
I don't really think that the documentation is poor, but it is not always easy to read. Some things are not spelled out as clearly as you would like, and some things are only mentioned once and not exactly where you expect it.
---
b { font-weight: normal; }
|
|
|
|
|
Guffa wrote: You seem to fail to see the similarities.
because the similarities are not documented.
Guffa wrote: You never get direct access to an open file through the framework. You access files through streams, readers and writers.
that completely misses the point
Guffa wrote: If you don't tell it anything and just leave it hanging, it can't close the file.
it closes the file when it succeeds, but leaves the file open when it fails. if it knows how to do it in one case, it should know how to do it in the other.
what is gained by having code do something as potentially problematic as leaving a file open in one case, but not another, and not telling callers that this happens ?
would you ever write code that behaved that way? i wouldn't.
Guffa wrote: Some things are not spelled out as clearly as you would like, and some things are only mentioned once and not exactly where you expect it.
that's pretty much the definition of "poor documentation". the only thing worse is no documentation at all.
|
|
|
|
|
Chris Losinger wrote: because the similarities are not documented.
Why do you complain about it being inconsistent then?
Chris Losinger wrote: that completely misses the point
Does it? If you use an XmlReader to open a file, don't you expect the file to be opened? Is it just that the method doesn't have "File" and "Open" in the name?
Chris Losinger wrote: it closes the file when it succeeds, but leaves the file open when it fails. if it knows how to do it in one case, it should know how to do it in the other.
Just because you do something that causes an exception, that doesn't automatically mean that you don't want to use the reader any more.
Chris Losinger wrote: that's pretty much the definition of "poor documentation".
Then you really haven't seen any poor documentation...
---
b { font-weight: normal; }
|
|
|
|
|
Guffa wrote: If you use an XmlReader to open a file, don't you expect the file to be opened?
of course. but i also expect it to be closed.
if you open a file, and you don't expect (or even allow) the caller to do anything with the file you've opened, then there is absolutely no reason for you to keep the file open - especially after you've gone out of scope.
|
|
|
|
|
Chris Losinger wrote:
of course. but i also expect it to be closed.
Yes, if you close the reader, it will close the file.
Chris Losinger wrote: if you open a file, and you don't expect (or even allow) the caller to do anything with the file you've opened, then there is absolutely no reason for you to keep the file open
How do you expect the reader to read from the file if it's not kept open?
Chris Losinger wrote: - especially after you've gone out of scope.
Yes, there is no reason to keep the file open after that, but the problem is that it has no relevance at all from the object's point of view. The object has no way of telling that the reference to it has gone out of scope.
---
b { font-weight: normal; }
|
|
|
|
|
Guffa wrote: Yes, if you close the reader, it will close the file.
the reader closes the file just fine if everything works. it clearly knows how to close the file that it opened without any assistance from me.
Guffa wrote: How do you expect the reader to read from the file if it's not kept open?
i don't expect it to keep reading at all - it threw an exception. if it could keep reading, it should've just kept reading.
i've had enough.
|
|
|
|
|
Chris Losinger wrote: the reader closes the file just fine if everything works. it clearly knows how to close the file that it opened without any assistance from me.
As I said before, if it knows that you can't use it any more, it can close the file. If you don't read the file to the end, it won't know this, and it doesn't know your opinion of when it can be closed.
Chris Losinger wrote: i don't expect it to keep reading at all - it threw an exception. if it could keep reading, it should've just kept reading.
As I said before, just because there is an exception it doesn't automatically mean that you can't continue to read from it. You just chose not to, and the reader is not aware of your decision as you haven't told it.
---
b { font-weight: normal; }
|
|
|
|
|
Guffa wrote: if it knows that you can't use it any more, it can close the file. If you don't read the file to the end, it won't know this, and it doesn't know your opinion of when it can be closed.
it opened the file. if i wanted control of the file outside of the context of an XmlReader, i would've created a StreamReader and gave that to the XmlReader. but i didn't - i gave XmlReader a filename and it opened the file. let me repeat that: XmlReader opened the file.
Guffa wrote: You just chose not to, and the reader is not aware of your decision as you haven't told it.
my decision was made by the fact that i called the thing via the interface that implies "here, you handle the file operations, not me". i didn't give it an opened file. i gave it a filename.
i didn't say "open this file, do what you need, then leave it open for me", i gave it a filename. and, the XmlReader provides no way to get to that opened file once it's opened it, so your statement that i can "continue to read from it" is completly meaningless - XmlReader provides no access to the opened file stream.
|
|
|
|
|
Chris Losinger wrote: it opened the file. if i wanted control of the file outside of the context of an XmlReader, i would've created a StreamReader and gave that to the XmlReader. but i didn't - i gave XmlReader a filename and it opened the file. let me repeat that: XmlReader opened the file.
Yes, you asked the reader to open the file. If you tell it to close it, it will. If you don't tell it to close it but leave it hanging in the middle of the process, it can't close the file as it doesn't know that you don't want to continue reading from it.
If you don't tell the reader that you don't want to use the file any more, how do you expect it to close the file?
my decision was made by the fact that i called the thing via the interface that implies "here, you handle the file operations, not me". i didn't give it an opened file. i gave it a filename.
Yes, and it does handle the file operations, according to the information that you give to the reader. If the reader has no information that you are done reading from the file, it can't close it.
i didn't say "open this file, do what you need, then leave it open for me"
Yes, you did. You opened it and stopped reading in the middle. Of course it stays open until you complete the read or closes it.
the XmlReader provides no way to get to that opened file once it's opened it, so your statement that i can "continue to read from it" is completly meaningless - XmlReader provides no access to the opened file stream.
It's not meaningless at all. You read from the file using the methods of the reader, it's irrelevant if you have direct access to the file or not.
It's exactly the same as with a stream. You use the methods of the stream to read from a file, but you never have direct access the the file.
---
b { font-weight: normal; }
|
|
|
|
|
Guffa wrote: If you don't tell the reader that you don't want to use the file any more, how do you expect it to close the file?
the exact same way it does when it finishes without an exception. why is that so hard for you to understand ?
|
|
|
|
|
Chris Losinger wrote: the exact same way it does when it finishes without an exception. why is that so hard for you to understand ?
I understand how you wish that it would work. I want you to explain how in the world you can expect it to work that way?
I have already told you that the reader can't close the file until you tell the reader that you don't want to use it any more. If you just leave it hanging halfway through the read, it doesn't know that you have decided not to read anything more.
It's just like if you pack up your car to go to Alaska, but halfways you run into a roadblock telling you to take another route. If you just step out of the car, leave it running and go to find a bar instead, the car won't figure out that you don't want to drive any further and shut itself down. It will just keep waiting until it runs out of gas.
The same thing happens to the reader that you left hanging. It will just keep waiting until the garbage collector comes and tells it to pack up and go.
---
b { font-weight: normal; }
|
|
|
|
|
|
Chris Losinger wrote: that's just silly. surely you can see the difference between a function called "File.Open" and one called "XmlReader.Create".
For my last 10+ years of C++ and C# development both a Create and Open interface will open a file. Open opens an exising file and File.Create creates a new file which is then opened.
Chris Losinger wrote: at best, this function is inconsistent in behavior and poorly-documented
It may be poorly documented, but it is consistent with my last 10+ years of experience with a Microsoft development framework.
|
|
|
|
|
Your right about the class being poorly documented. It's not a bug with the class, but with the people who wrote it.
In the XmlReader class, there is, thankfully, a property called ReadState that you can check in your code to see if the was actually opened or not. The possible values are Closed, EndOfFile, Error, Initial, and Interactive. Docs on it are here[^].
You can either use Guffa's version or just call the Dispose() method on the XmlReader in your catch block. If the file hasn't been opened, nothing will happen if you call Dispose on the reader.
-- modified at 10:56 Friday 6th October, 2006
Changed Close to Dispose. That's what I get for spending entire day and night writing in VBScript...
Dave Kreskowiak
Microsoft MVP - Visual Basic
|
|
|
|
|
Dave Kreskowiak wrote: a property called ReadState that you can check in your code to see if the was actually opened or not
ah. that's good to know. thanks.
|
|
|
|
|
Hello all,
I'm using .NET 2005 and I have to convert a collection (CustomCollection) into a List, from Generics. I don't seem to find anything about it... Has anybody any idea if it is possible to do this conversion without copying every object from the collection to the list (only a conversion) and if it's possible... how should i do that??
Please help...
Thank you!
Roxana
|
|
|
|
|
Hi,
basically you will have to copy the contents. You could make this by either copying everything yourself or by using the CopyTo method of the collection to copy everything into an array and than either using the appropriate List constructor (one of them takes any IEnumerable) or using AddRange.
Robert
|
|
|
|
|