I've got something like the code below...someone here mentioned that the WebClient, Stream, and StreamReader objects could all benefit from using blocks. Two easy questions:
1: How would this little snippet look with using blocks? I've no problem with doing my own research so resource links are fine but it'd be quicker and easier to just see an example and I'll understand it from that.
2: I'd like to get in the habit of good coding standards, would help if I knew a little about the reasons why using blocks are better...is it just so you don't have to worry about closing or are there more reasons? Thanks!
WebClient client = new WebClient();
Stream stream = client.OpenRead(originGetterURL);
StreamReader reader = new StreamReader(stream);
JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(rea开发者_如何学Pythonder.ReadLine());
string encryptionKey = (string)jObject["key"];
string originURL = (string)jObject["origin_url"];
stream.Close()
reader.Close()
using (var client = new WebClient())
using (var stream = client.OpenRead(originGetterURL))
using (var reader = new StreamReader(stream))
{
var jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());
var encryptionKey = (string)jObject["key"];
var originURL = (string)jObject["origin_url"];
}
or simply:
using (var client = new WebClient())
{
var json = client.DownloadString(originGetterURL);
var jObject = Newtonsoft.Json.Linq.JObject.Parse(json);
var encryptionKey = (string)jObject["key"];
var originURL = (string)jObject["origin_url"];
}
using (WebClient client = new WebClient())
{
// do work
}
Provides a convenient syntax that ensures the correct use of IDisposable objects.
From MSDN: using Statement (C# Reference)
As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.
using(WebClient client = new WebClient()) {
}
is the same as
WebClient client;
try {
client = new WebClient();
} finally {
if(client != null) {
client.Dispose();
}
}
A lot easier to use using
Its simple :
Using *using*
is not "good practice" as such, more a short way (syntactic sugar) of disposing objects that you should be disposing. Things like Files, Connections to a Database and in your case a network.
You would do something like:
using(WebClient we = new WebClient))
{
//do something with 'we' here
}
This is basically just a shortcut for using the variable we
normally and then calling we.Dispose()
which does a clean up.
Syntax :
using (<Any class that Implements IDisposable>)
{
//use the class
}
Other SO questions you should see:
What is the relationship between the using keyword and the IDisposable interface?
using various types in a using statement (C#)
using {} blocks simply call Dispose() at the closing brace--or rather, tell the Garbage Collector that it can dispose of the object. You'd use it like:
using (WebClient client = new WebClient())
{
Stream stream = client.OpenRead(originGetterURL); StreamReader reader = new StreamReader(stream);
JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine()); string encryptionKey = (string)jObject["key"]; string originURL = (string)jObject["origin_url"];
stream.Close() reader.Close()
} // 'client' instance gets disposed here
Something like this:
using(WebClient client = new WebClient())
using(Stream stream = client.OpenRead(originGetterURL))
StreamReader reader = new StreamReader(stream) {
JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());
string encryptionKey = (string)jObject["key"];
string originURL = (string)jObject["origin_url"];
}
As for why using
blocks are good, and better than manually calling Dispose... image if any of the code in that using
block threw an exception before you hit the lines where you close everything? You'd essentially leak whatever unmanaged resource the IDisposable object is managing under the hood. using
ensures that Dispose is called correctly, even in the face of an exception (by essentially injecting the appropriate try/finally block).
When possible (i.e., you don't have to preserve the lifetime of some IDisposable across scopes), you should leverage using
blocks if for no other reason than they reduce the amount of boilerplate code you have to write in order to ensure your own code is safe and correct.
@Darin's answer shows the code. The reason they are good is that using blocks cause the compiler to spit out code that will automatically call "Dispose" on the object (to have it immediately release any resources it may be using) before exiting the block - even if an exception gets thrown within with the block
using
is equivalent to try.. finally
so the disposer will run even if an exception is thrown within the block.
There are 2 reasons for using-blocks:
- They look good
- The code inside the block often could throw exceptions. So you wold need try-finally
In the end a using-block e.g.
using (Somthing somthing=...)
{
DoActions(somthing);
}
is identical to the followin contstruct:
{Somthing somthing=...
try
{
DoActions(somthing);
}
finally
{
somthing.Dispose();
}
}//the outer bracket limits the variable
精彩评论