C # "использование" блоков - PullRequest
5 голосов
/ 21 января 2011

У меня есть что-то вроде приведенного ниже кода ... кто-то здесь упомянул, что все объекты WebClient, Stream и StreamReader могут выиграть от использования блоков. Два простых вопроса:

1: Как будет выглядеть этот маленький фрагмент с использованием блоков? У меня нет проблем с проведением собственных исследований, поэтому ссылки на ресурсы в порядке, но было бы проще и быстрее увидеть пример, и я пойму это из этого.

2: Я хотел бы привыкнуть к хорошим стандартам кодирования, помог бы, если бы я немного знал о причинах, по которым использование блоков лучше ... это просто, чтобы вам не пришлось беспокоиться о закрытии или есть еще причины? Спасибо!

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()

Ответы [ 9 ]

9 голосов
/ 21 января 2011
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"];
}

или просто:

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"];
}
5 голосов
/ 21 января 2011
using (WebClient client = new WebClient())
{
    // do work
}

Предоставляет удобный синтаксис, обеспечивающий правильное использование IDisposable объектов.

Из MSDN: с использованием Statement (C #Ссылка)


Как правило, когда вы используете объект IDisposable, вы должны объявить и создать его экземпляр в операторе using. Использованиеоператор вызывает метод Dispose для объекта правильным образом, а также заставляет сам объект выходить из области видимости, как только вызывается Dispose.Внутри блока using объект доступен только для чтения и не может быть изменен или переназначен.


Оператор using обеспечивает вызов метода Dispose, даже если во время исключения возникаетВы вызываете методы для объекта. Вы можете достичь того же результата, поместив объект в блок try и затем вызвав Dispose в блоке finally;на самом деле, именно так оператор using переводится компилятором.

4 голосов
/ 21 января 2011
using(WebClient client = new WebClient()) {

}

совпадает с

WebClient client;
try {
    client = new WebClient();
} finally {
    if(client != null) {
        client.Dispose();
    }
}

Намного проще использовать

2 голосов
/ 21 января 2011

Это просто:

Использование *using* не является «хорошей практикой» как таковой, это более короткий путь (синтаксический сахар) утилизации предметов, которые вы должны утилизировать. Такие вещи, как файлы, подключения к базе данных и в вашем случае сети.

Вы бы сделали что-то вроде:

using(WebClient we = new WebClient))
{
//do something with 'we' here
}

Это просто ярлык для обычного использования переменной we и последующего вызова we.Dispose(), который выполняет очистку.

Синтаксис:

using (<Any class that Implements IDisposable>)
{
//use the class
}

Другие вопросы SO, которые вы должны увидеть:
Какая связь между ключевым словом using и интерфейсом IDisposable?
использование различных типов в операторе using (C #)

1 голос
/ 21 января 2011

Существует 2 причины использования блоков:

  • Они хорошо выглядят
  • Код внутри блока часто может вызывать исключения.Так что вам понадобится try-finally

В конце блок использования, например

using (Somthing somthing=...)
{
    DoActions(somthing);
}

, идентичен следующему конструкту:

{Somthing somthing=...
    try
    {
        DoActions(somthing);
    }
    finally
    {
        somthing.Dispose();
    }
}//the outer bracket limits the variable
1 голос
/ 21 января 2011

using эквивалентно try.. finally, поэтому устройство удаления будет работать, даже если в блоке возникло исключение.

1 голос
/ 21 января 2011

@ В ответе Дарина указан код.Причина, по которой они хороши, заключается в том, что использование блоков приводит к тому, что компилятор выплевывает код, который будет автоматически вызывать «Dispose» для объекта (чтобы он немедленно высвободил все ресурсы, которые он может использовать) перед выходом из блока - даже если генерируется исключениевнутри с блоком

1 голос
/ 21 января 2011

Примерно так:

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"];
}

Что касается того, почему блоки using хороши и лучше, чем ручной вызов Dispose ... image, если какой-либо код в этом блоке using вызвал исключениепрежде чем вы попадете в строки, где вы закрываете все?По сути, вы бы пропустили любой неуправляемый ресурс, которым IDisposable-объект управляет изнутри.using гарантирует, что Dispose вызывается правильно, даже при наличии исключения (по сути, путем внедрения соответствующего блока try / finally).

По возможности (т. Е. Вам не нужно сохранять время жизнинекоторые IDisposable в разных областях), вы должны использовать блоки using, если только по той причине, что они уменьшают количество шаблонного кода, который вы должны написать, чтобы гарантировать, что ваш собственный код безопасен и корректен.

1 голос
/ 21 января 2011

используя блоки {}, просто вызовите Dispose () в закрывающей фигурной скобке - или, скорее, скажите сборщику мусора, что он может избавиться от объекта. Вы бы использовали это как:

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
...