it-swarm-ru.tech

Каковы виды использования «using» в C #

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

289
ubermonkey

Причина оператора 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();
    }
}
440
paulwhit

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

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

Вещи как это:

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

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

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

95
Joel Coehoorn

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

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

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

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

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

21
David Mitchell

В документации 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
Aureliano Buendia

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

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

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

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

8
Pluc

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

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using
6
Lucas

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

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

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


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

5
Konrad Rudolph

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

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
4
VictorySaber

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

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

4
Joel Martinez
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 
            }
    }
3
Shiraj Momin

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

3
Joseph Daigle

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

3
David Arno

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

1
deepak samantaray

Существует два варианта использования ключевого слова в 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/

1
Chamila Maddumage

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

Другое имя для обработки ошибок было бы Nice, и, возможно, как-то более очевидным.

1
Seb

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

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

}
1
Siamand Maroufi

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

1
Scot McPherson

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

1
Gilligan

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

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

1
snowell

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

1
Grank

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

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

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

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

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

1
David Basarab

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

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);
    }
}
1
Brendan Kendrick

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

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

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

Пример:

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