Каковы виды использования «using» в C # - PullRequest
289 голосов
/ 16 сентября 2008

Пользователь kokos ответил на замечательный вопрос Скрытые возможности C # , упомянув ключевое слово using. Можете ли вы уточнить это? Каковы виды использования using?

Ответы [ 29 ]

440 голосов
/ 16 сентября 2008

Причина оператора using состоит в том, чтобы гарантировать, что объект удаляется, как только он выходит из области видимости, и ему не требуется явный код для обеспечения этого.

Как и в Понимая оператор использования в C # , .NET CLR преобразует

using (MyResource myRes = new MyResource())
{
    myRes.DoSomething();
}

до

{ // Limits scope of myRes
    MyResource myRes= new MyResource();
    try
    {
        myRes.DoSomething();
    }
    finally
    {
        // Check for a null resource.
        if (myRes != null)
            // Call the object's Dispose method.
            ((IDisposable)myRes).Dispose();
    }
}
121 голосов
/ 16 сентября 2008

Так как многие люди до сих пор делают:

using (System.IO.StreamReader r = new System.IO.StreamReader(""))
using (System.IO.StreamReader r2 = new System.IO.StreamReader("")) {
   //code
}

Я думаю, многие люди до сих пор не знают, что вы можете сделать:

using (System.IO.StreamReader r = new System.IO.StreamReader(""), r2 = new System.IO.StreamReader("")) {
   //code
}
95 голосов
/ 16 сентября 2008

Вещи как это:

using (var conn = new SqlConnection("connection string"))
{
   conn.Open();

    // Execute SQL statement here on the connection you created
}

Этот SqlConnection будет закрыт без необходимости явного вызова функции .Close(), и это произойдет , даже если выброшено исключение , без необходимости try / catch /finally.

30 голосов
/ 16 сентября 2008

используя можно использовать для вызова IDisposable. Он также может быть использован для псевдонимов типов.

using (SqlConnection cnn = new SqlConnection()) { /*code*/}
using f1 = System.Windows.Forms.Form;
21 голосов
/ 15 октября 2008

используя, в смысле

using (var foo = new Bar())
{
  Baz();
}

На самом деле является сокращением для блока try / finally. Это эквивалентно коду:

var foo = new Bar();
try
{
  Baz();
}
finally
{
  foo.Dispose();
}

Вы заметите, конечно, что первый фрагмент гораздо более краткий, чем второй, а также что есть много разных вещей, которые вы, возможно, захотите сделать для очистки, даже если выдается исключение. Из-за этого мы создали класс, который мы называем Scope, который позволяет вам выполнять произвольный код в методе Dispose. Так, например, если у вас есть свойство IsWorking, которое вы всегда хотели установить в false после попытки выполнить операцию, вы бы сделали это так:

using (new Scope(() => IsWorking = false))
{
  IsWorking = true;
  MundaneYetDangerousWork();
}

Вы можете узнать больше о нашем решении и о том, как мы его получили здесь .

10 голосов
/ 25 декабря 2015

Документация Microsoft гласит, что с использованием имеет двойную функцию (https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx), как в виде директивы , так и в инструкциях . Как В выражении , как указывалось здесь в других ответах, ключевое слово - это, по сути, синтаксический сахар, определяющий область действия для размещения IDisposable объекта. Как директива , оно обычно используется для импорта пространств имен и типов. Также в качестве директивы вы можете создать псевдонимы для пространств имен и типов, как указано в книге "C # 5.0 в двух словах: полное руководство" (http://www.amazon.com/5-0-Nutshell-The-Definitive-Reference-ebook/dp/B008E6I1K8), Джозефом и Беном Албахари. Один пример:

namespace HelloWorld
{
    using AppFunc = Func<IDictionary<DateTime, string>, List<string>>;
    public class Startup
    {
        public static AppFunc OrderEvents() 
        {
            AppFunc appFunc = (IDictionary<DateTime, string> events) =>
            {
                if ((events != null) && (events.Count > 0))
                {
                    List<string> result = events.OrderBy(ev => ev.Key)
                        .Select(ev => ev.Value)
                        .ToList();
                    return result;
                }
                throw new ArgumentException("Event dictionary is null or empty.");
            };
            return appFunc;
        }
    }
}

Это что-то, что нужно принимать с умом, поскольку злоупотребление этой практикой может повредить ясности кода. В DotNetPearls есть хорошее объяснение псевдонимов C #, а также упоминания о плюсах и минусах (http://www.dotnetperls.com/using-alias).

10 голосов
/ 16 сентября 2008

В прошлом я много использовал его для работы с потоками ввода и вывода. Вы можете удобно их вкладывать, и это устраняет множество потенциальных проблем, с которыми вы обычно сталкиваетесь (автоматически вызывая dispose). Например:

        using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
        {
            using (BufferedStream bs = new BufferedStream(fs))
            {
                using (System.IO.StreamReader sr = new StreamReader(bs))
                {
                    string output = sr.ReadToEnd();
                }
            }
        }
8 голосов
/ 27 апреля 2015

Просто добавив немного чего-то, что меня удивило, не подошло. Самая интересная особенность использования (на мой взгляд) заключается в том, что независимо от того, как вы выходите из блока использования, он всегда будет располагать объектом. Это включает в себя возвраты и исключения.

using (var db = new DbContext())
{
    if(db.State == State.Closed) throw new Exception("Database connection is closed.");
    return db.Something.ToList();
}

Не имеет значения, было ли выброшено исключение или возвращен список. Объект DbContext всегда будет расположен.

6 голосов
/ 16 сентября 2008

Еще одно замечательное применение - это создание модального диалога.

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using
5 голосов
/ 16 сентября 2008

В заключение, когда вы используете локальную переменную типа, который реализует IDisposable, всегда , без исключения используйте using 1 .

Если вы используете нелокальные IDisposable переменные, то всегда реализует шаблон IDisposable .

Два простых правила, без исключения 1 . Предотвращение утечек ресурсов в противном случае является настоящей болью в * ss.


1) : Единственное исключение - когда вы обрабатываете исключения. Тогда может быть меньше кода для явного вызова Dispose в блоке finally.

...