Каково использование слова "использование" в C#?

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

Это способ C# поддержки идиомы RAII: hackcraft.net/raii

Nemanja Trifunovic 16.09.2008 22:35

Вы можете использовать для объектов, в которых реализован интерфейс IDispose. Использование вызовет метод Dispose, когда этот объект выходит за пределы области видимости. Он гарантирует вызов Dispose даже в случае возникновения какого-либо исключения. Он работает как предложение finally и выполняет Dispose.

CharithJ 04.07.2015 04:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
333
2
290 920
29
Перейти к ответу Данный вопрос помечен как решенный

Ответы 29

При использовании ADO.NET вы можете использовать ключевое слово для таких вещей, как объект подключения или объект чтения. Таким образом, когда блок кода завершится, он автоматически отключит ваше соединение.

Я бы просто добавил, что блок кода даже не нужно завершать. Блок using удалит ресурс даже в случае необработанного исключения.

harpo 16.09.2008 22:27

Чтобы еще больше уточнить, это способ убедиться, что сборщик мусора позаботится о ваших выделениях, когда вы этого хотите, вместо того, чтобы делать это, когда Это хочет.

moswald 16.09.2008 22:28

Вот такие вещи:

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

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

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

что, если я использую "using" внутри метода и возвращаюсь в середине использования. Есть какие-либо проблемы?

francisco_ssb 04.03.2016 17:51

Нет проблем. В приведенном здесь примере соединение все равно будет закрыто, даже если вы используете return из середины блока using.

Joel Coehoorn 04.03.2016 21:00

Rhino издевается над синтаксисом записи и воспроизведения интересно использует using.

это в основном то же самое, что и вызов Playback и Verify, все, что он просто делает в методах Dispose ()

George Mauer 16.09.2008 22:37

Благодаря комментариям ниже я немного поправлю этот пост (в то время мне не следовало использовать слова «сборка мусора», извиняюсь):
Когда вы используете using, он вызывает метод Dispose () для объекта в конце области видимости using. Таким образом, у вас может быть довольно много отличного кода очистки в вашем методе Dispose ().
Пункт списка, который, как мы надеемся, может получить это без разметки: если вы реализуете IDisposable, убедитесь, что вы вызываете GC.SuppressFinalize () в своей реализации Dispose (), иначе автоматическая сборка мусора попытается прийти и завершить его в какой-то момент. point, что, по крайней мере, было бы пустой тратой ресурсов, если вы уже использовали Dispose () d.

Имеет косвенный эффект. Поскольку вы удалили объект явным образом, он не требует завершения и, следовательно, может быть обработан сборщиком мусора раньше.

Kent Boogaart 16.09.2008 22:38

using можно использовать для вызова IDisposable. Его также можно использовать для псевдонимов типов.

using (SqlConnection cnn = new SqlConnection()) { /*code*/}
using f1 = System.Windows.Forms.Form;

"using" также может использоваться для разрешения конфликтов пространств имен. См. http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ для краткого руководства, которое я написал по этой теме.

Ключевое слово using определяет область действия объекта, а затем удаляет объект, когда область действия завершена. Например.

using (Font font2 = new Font("Arial", 10.0f))
{
    // use font2
}

См. Статью MSDN о ключевом слове using в C# в здесь.

с помощью используется, когда у вас есть ресурс, который вы хотите удалить после его использования.

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

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

Пример:

using (File file = new File (parameters))
{
    *code to do stuff with the file*
}
Ответ принят как подходящий

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

Как и в Понимание оператора using в C# (проект кода) и Использование объектов, реализующих IDisposable (microsoft), компилятор C# преобразует

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

В C# 8 представлен новый синтаксис под названием «с использованием деклараций»:

A using declaration is a variable declaration preceded by the using keyword. It tells the compiler that the variable being declared should be disposed at the end of the enclosing scope.

Таким образом, эквивалентный код, приведенный выше, будет:

using var myRes = new MyResource();
myRes.DoSomething();

И когда элемент управления выходит за пределы области действия (обычно это метод, но также может быть блок кода), myRes будет удален.

Обратите внимание, что это не обязательно связано с удалением объекта правильно, а скорее с тем, удаляется ли он своевременно. Объекты, реализующие IDisposable, которые удерживают неуправляемые ресурсы, такие как потоки и дескрипторы файлов, также будут реализовывать финализатор, который гарантирует, что Dispose вызывается во время сборки мусора. Проблема в том, что сборка мусора может не происходить относительно долгое время. using гарантирует, что Dispose будет вызван после завершения работы с объектом.

John Saunders 11.01.2012 22:53

Обратите внимание, что сгенерированный код немного отличается, если MyRessource является структурой. Теста на аннулирование явно нет, но и бокса на IDisposable тоже нет. Испускается ограниченный виртуальный вызов.

Romain Verdier 03.05.2014 18:31

@paulwhit: что, если конструктор выдает выше?

gmoniava 02.11.2015 00:00

@Giorgi, если конструктор MyResource генерирует исключение, значит, он не инициализировался должным образом и отвечает за удаление всего, что необходимо удалить, прежде чем генерировать исключение.

Trisped 14.01.2016 01:04

Почему никто не упоминает, что using также используется для импорта пространств имен?

Kyle Delaney 13.01.2017 02:35

Обратите внимание, что если вы напишете непосредственно вторую версию кода, результат будет другим. Если вы используете using, встроенная в него переменная доступна только для чтения. Этого невозможно добиться для локальных переменных без оператора using.

Massimiliano Kraus 24.11.2017 19:08

Для тех, кто пришел из страны питонов, это эквивалентно чему-то вроде with open(filename) as f: # blah?

Chromium 18.07.2018 10:09

@JohnSaunders Кроме того, вызов финализатора не гарантируется.

Pablo H 10.05.2019 15:17

Интересно, что вы также можете использовать шаблон using / IDisposable для других интересных вещей (например, в другой точке способа, которым его использует Rhino Mocks). В принципе, вы можете воспользоваться тем фактом, что компилятор вызовет всегда .Dispose для "используемого" объекта. Если у вас есть что-то, что должно произойти после определенной операции ... что-то, что имеет определенное начало и конец ... тогда вы можете просто создать класс IDisposable, который запускает операцию в конструкторе, а затем завершается в методе Dispose.

Это позволяет вам использовать действительно приятный синтаксис using для обозначения явного начала и конца указанной операции. Так же работает и System.Transactions.

В прошлом я много использовал его для работы с потоками ввода и вывода. Вы можете аккуратно вложить их, и это устранит множество потенциальных проблем, с которыми вы обычно сталкиваетесь (автоматически вызывая 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();
                }
            }
        }

Не то чтобы это было очень важно, но с помощью можно также менять ресурсы на лету. Да, одноразовые, как упоминалось ранее, но, возможно, конкретно вам не нужны ресурсы, которые они не соответствуют другим ресурсам во время остальной части вашего выполнения. Итак, вы хотите утилизировать его, чтобы он не мешал где-либо еще.

Поскольку многие люди до сих пор это делают:

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
}

Можно ли использовать несколько объектов разных типов в одном операторе using?

Agnel Kurian 24.04.2013 16:12

@AgnelKurian Нет: "ошибка CS1044: невозможно использовать более одного типа в операторе for, using, fixed или объявления"

David Sykes 23.01.2014 13:00

Как это отвечает на вопрос?

Liam 15.11.2017 14:36

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

kub1x 12.10.2018 10:58

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

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

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


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

Другой пример разумного использования, при котором объект немедленно удаляется:

using (IDataReader myReader = DataFunctions.ExecuteReader(CommandType.Text, sql.ToString(), dp.Parameters, myConnectionString)) 
{
    while (myReader.Read()) 
    {
        MyObject theObject = new MyObject();
        theObject.PublicProperty = myReader.GetString(0);
        myCollection.Add(theObject);
    }
}

Еще одно прекрасное применение using - создание экземпляра модального диалога.

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using

Вы имели в виду frm.ShowDialog?

StayOnTarget 07.12.2017 23:37

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

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

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

Все, что находится за пределами фигурных скобок, удаляется, поэтому хорошо избавляться от ваших объектов, если вы их не используете. Это потому, что если у вас есть объект SqlDataAdapter, и вы используете его только один раз в жизненном цикле приложения, и вы заполняете только один набор данных, и он вам больше не нужен, вы можете использовать код:

using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
   // do stuff
} // here adapter_object is disposed automatically

public class ClassA:IDisposable

{
   #region IDisposable Members        
    public void Dispose()
    {            
        GC.SuppressFinalize(this);
    }
    #endregion
}

public void fn_Data()

    {
     using (ClassA ObjectName = new ClassA())
            {
                //use objectName 
            }
    }

Использование Clause используется для определения области действия конкретной переменной. Например:

     Using(SqlConnection conn=new SqlConnection(ConnectionString)
            {
                Conn.Open()
            // Execute sql statements here.
           // You do not have to close the connection explicitly here as "USING" will close the connection once the object Conn becomes out of the defined scope.
            }

Это может ввести кого-то в заблуждение, используя его для утилизации предметов. Возможно, вы путаете это с блоком кода, если вы хотите ограничить область действия переменной, вы можете использовать для этого вложенный блок кода: public static void Main (params string [] args) {{// вложенный блок кода}}

luiseduardohd 16.08.2019 01:46

@luise .. верно. 1. Использование используется для освобождения памяти, потребляемой объектами.

Riya Patil 17.02.2021 01:39

Вы можете использовать пространство имен псевдонима в следующем примере:

using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;

Это называется с помощью директивы псевдонима, поскольку, как видите, его можно использовать для скрытия многословных ссылок, если вы хотите, чтобы в коде было очевидно, что вы имеете в виду. например

LegacyEntities.Account

вместо

CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account

или просто

Account   // It is not obvious this is a legacy entity

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

Это происходит от: здесь

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

Было бы неплохо другое название для обработки ошибок, а может быть, и более очевидное.

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

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

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

В документации Microsoft указано, что с помощью имеет двойную функцию (https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx), как директива, так и в заявления. Как утверждение, как было указано здесь в других ответах, ключевое слово в основном является синтаксическим сахаром для определения области для удаления объекта IDisposable. Как директива, он обычно используется для импорта пространств имен и типов. Также в качестве директивы вы можете создать псевдонимы для пространств имен и типов, как указано в книге Джозефа и Бена Альбахари «C# 5.0 In a Nutshell: The Definitive Guide» (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 (http://www.dotnetperls.com/using-alias) есть хорошее объяснение псевдонимов C#, в котором также упоминаются плюсы и минусы.

Не буду лгать: я ненавидеть использовал using как инструмент псевдонима. Меня это смущает при чтении кода - я уже знаю, что System.Collections существует и имеет класс IEnumerable<T>. Использование псевдонима, чтобы назвать это чем-то еще, запутывает меня. Я рассматриваю using FooCollection = IEnumerable<Foo> как способ заставить более поздних разработчиков прочитать код и подумать: «Что, черт возьми, такое FooCollection и почему для него где-то нет класса?» Я никогда не использую его и не одобряю его использования. Но это может быть только я.

Ari Roth 28.12.2017 22:08

Приложение: я допускаю, что иногда он может быть использован, как в вашем примере, где вы используете его для определения делегата. Но я бы сказал, что это относительно редко.

Ari Roth 28.12.2017 22:10

Его также можно использовать для создания областей, например:

class LoggerScope:IDisposable {
   static ThreadLocal<LoggerScope> threadScope = 
        new ThreadLocal<LoggerScope>();
   private LoggerScope previous;

   public static LoggerScope Current=> threadScope.Value;

   public bool WithTime{get;}

   public LoggerScope(bool withTime){
       previous = threadScope.Value;
       threadScope.Value = this;
       WithTime=withTime;
   }

   public void Dispose(){
       threadScope.Value = previous;
   }
}


class Program {
   public static void Main(params string[] args){
       new Program().Run();
   }

   public void Run(){
      log("something happend!");
      using(new LoggerScope(false)){
          log("the quick brown fox jumps over the lazy dog!");
          using(new LoggerScope(true)){
              log("nested scope!");
          }
      }
   }

   void log(string message){
      if (LoggerScope.Current!=null){
          Console.WriteLine(message);
          if (LoggerScope.Current.WithTime){
             Console.WriteLine(DateTime.Now);
          }
      }
   }

}

Оператор using сообщает .NET освободить объект, указанный в блоке using, если он больше не нужен. Таким образом, вы должны использовать блок using для классов, которые требуют очистки после них, например типов System.IO.

using as a statement automatically calls the dispose on the specified object. The object must implement the IDisposable interface. It is possible to use several objects in one statement as long as they are of the same type.

CLR преобразует ваш код в MSIL. И оператор using переводится в блок try and finally. Вот как оператор using представлен в IL. Заявление об использовании переводится на три части: приобретение, использование и выбытие. Ресурс сначала приобретается, затем использование включается в оператор try с предложением finally. Затем объект помещается в предложение finally.

В C# есть два следующих использования ключевого слова using.

  1. Как директива

    Обычно мы используем ключевое слово using для добавления пространств имен в файлы кода и классы. Затем он делает доступными все классы, интерфейсы и абстрактные классы, а также их методы и свойства на текущей странице.

    Пример:

    using System.IO;
    
  2. Как заявление

    Это еще один способ использования ключевого слова using в C#. Он играет жизненно важную роль в повышении производительности сборки мусора.

    Оператор using гарантирует, что Dispose () вызывается, даже если возникает исключение, когда вы создаете объекты и вызываете методы, свойства и так далее. Dispose () - это метод, присутствующий в интерфейсе IDisposable, который помогает реализовать настраиваемую сборку мусора. Другими словами, если я выполняю какую-либо операцию с базой данных (Insert, Update, Delete), но каким-то образом возникает исключение, то здесь оператор using автоматически закрывает соединение. Нет необходимости явно вызывать метод соединения Close ().

    Еще один важный фактор - это то, что это помогает в пуле подключений. Пул соединений в .NET помогает избежать многократного закрытия соединения с базой данных. Он отправляет объект подключения в пул для будущего использования (следующий вызов базы данных). При следующем вызове соединения с базой данных из вашего приложения пул соединений выбирает объекты, доступные в пуле. Таким образом, это помогает повысить производительность приложения. Поэтому, когда мы используем оператор using, контроллер автоматически отправляет объект в пул соединений, нет необходимости явно вызывать методы Close () и Dispose ().

    Вы можете сделать то же самое, что и оператор using, используя блок try-catch и явно вызвать Dispose () внутри блока finally. Но оператор using выполняет вызовы автоматически, чтобы сделать код более чистым и элегантным. Внутри блока using объект доступен только для чтения и не может быть изменен или переназначен.

    Пример:

    string connString = "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;";
    
    using (SqlConnection conn = new SqlConnection(connString))
    {
          SqlCommand cmd = conn.CreateCommand();
          cmd.CommandText = "SELECT CustomerId, CompanyName FROM Customers";
          conn.Open();
          using (SqlDataReader dr = cmd.ExecuteReader())
          {
             while (dr.Read())
             Console.WriteLine("{0}\t{1}", dr.GetString(0), dr.GetString(1));
          }
    }
    

В предыдущем коде я не закрываю никаких соединений; он закроется автоматически. Оператор using вызовет conn.Close () автоматически из-за оператора using (using (SqlConnection conn = new SqlConnection(connString)) и то же самое для объекта SqlDataReader. А также, если произойдет какое-либо исключение, оно автоматически закроет соединение.

Для получения дополнительной информации см. Использование и важность использования в C#.

Другие вопросы по теме