Каково использование слова «использование» в C#

StackOverflow https://stackoverflow.com/questions/75401

  •  09-06-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

Как в Понимание оператора 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();
    }
}

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

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

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 (var conn = new SqlConnection("connection string"))
{
   conn.Open();

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

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

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

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

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

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

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

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

В документации Microsoft указано, что с использованием имеет двойную функцию (https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx), как директива И в заявления.Как заявление, как было указано здесь в других ответах, ключевое слово в основном представляет собой синтаксический сахар, определяющий область действия для удаления IDодноразовый объект.Как директива, он обычно используется для импорта пространств имен и типов.Также в качестве директивы вы можете создать псевдонимы для пространств имен и типов, как указано в книге «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).

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

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

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

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

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using

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

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

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


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

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

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

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

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

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

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

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

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

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

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

Пример:

using (File file = new File (parameters))
{
    *code to do stuff with the file*
}

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

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

Видеть здесь для статьи MSDN по ключевому слову C# using.

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

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

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

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

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

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

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

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

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

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

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

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 в C#.

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

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

Бывший:

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

Это еще один способ использования ключевого слова using в C#.Он играет жизненно важную роль в повышении производительности сборки мусора.Оператор using гарантирует, что Dispose() будет вызван, даже если при создании объектов и вызове методов, свойств и т. д. возникает исключение.Dispose() — это метод, присутствующий в интерфейсе IDisposable, который помогает реализовать собственную сборку мусора.Другими словами, если я выполняю какую-либо операцию с базой данных (вставка, обновление, удаление), но каким-то образом возникает исключение, то здесь оператор 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.А также, если возникнет какое-либо исключение, соединение автоматически закроется.

Для получения дополнительной информации --> https://www.c-sharpcorner.com/UploadFile/manas1/usage-and-importance-of-using-in-C-Sharp472/

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

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

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

     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.
            }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top