Pergunta

Do utilizador kokos respondeu o maravilhoso Recursos ocultos do C# pergunta, mencionando o using palavra-chave.Você pode explicar isso?Quais são os usos using?

Foi útil?

Solução

A razão para using declaração é garantir que o objeto seja descartado assim que sair do escopo e não requer código explícito para garantir que isso aconteça.

Como em Compreendendo a instrução 'using' em C#, o .NET CLR converte

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

para

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

Outras dicas

Já que muitas pessoas ainda fazem:

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

Acho que muitas pessoas ainda não sabem o que você pode fazer:

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

Coisas assim:

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

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

Esse SqlConnection será fechado sem a necessidade de chamar explicitamente o .Close() função, e isso vai acontecer mesmo se uma exceção for lançada, sem a necessidade de um try/catch/finally.

using pode ser usado para chamar IDisposable.Também pode ser usado para tipos de alias.

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

usando, no sentido de

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

Na verdade, é uma abreviação para um bloco try/finally.É equivalente ao código:

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

Você notará, é claro, que o primeiro trecho é muito mais conciso que o segundo e também que há muitos tipos de coisas que você pode querer fazer como limpeza, mesmo que uma exceção seja lançada.Por causa disso, criamos uma classe que chamamos de Scope, que permite executar código arbitrário no método Dispose.Então, por exemplo, se você tivesse uma propriedade chamada IsWorking que sempre quis definir como falsa depois de tentar realizar uma operação, você faria assim:

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

Você pode ler mais sobre nossa solução e como a derivamos aqui.

Eu usei muito no passado para trabalhar com fluxos de entrada e saída.Você pode aninhá-los muito bem e isso elimina muitos dos problemas potenciais que você normalmente encontra (chamando descarte automaticamente).Por exemplo:

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

A documentação da Microsoft afirma que usando tem dupla função (https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx), tanto como diretiva e em declarações.Como um declaração, como foi apontado aqui em outras respostas, a palavra-chave é basicamente um açúcar sintático para determinar um escopo para descartar um IDisponível objeto.Como um diretiva, ele é usado rotineiramente para importar namespaces e tipos.Também como diretiva, você pode criar apelido para namespaces e tipos, conforme apontado no livro "C# 5.0 In a Nutshell:O guia definitivo" (http://www.amazon.com/5-0-Nutshell-The-Definitive-Reference-ebook/dp/B008E6I1K8), de Joseph e Ben Albahari.Um exemplo:

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

Isto é algo a ser adotado com sabedoria, já que o abuso dessa prática pode prejudicar a clareza do código.Há uma boa explicação sobre aliases C#, também mencionando prós e contras, em DotNetPearls (http://www.dotnetperls.com/using-alias).

Apenas adicionando algo que me surpreendeu não apareceu.A característica mais interessante do using (na minha opinião) é que não importa como você sai do bloco using, ele sempre descartará o objeto.Isso inclui devoluções e exceções.

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

Não importa se a exceção é lançada ou a lista é retornada.O objeto DbContext sempre será descartado.

Outro ótimo uso de using é ao instanciar um diálogo modal.

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using

Concluindo, quando você usa uma variável local de um tipo que implementa IDisposable, sempre, sem exceção, use using1.

Se você usar não local IDisposable variáveis, então sempre implementar o IDisposable padrão.

Duas regras simples, sem exceção1.Prevenir vazamentos de recursos é uma verdadeira dor de cabeça.


1):A única exceção é quando você está lidando com exceções.Pode então ser menos código para chamar Dispose explicitamente no finally bloquear.

Curiosamente, você também pode usar o padrão using/IDisposable para outras coisas interessantes (como o outro ponto da maneira como o Rhino Mocks o usa).Basicamente, você pode aproveitar o fato de que o compilador irá sempre chame .Dispose no objeto "usado".Se você tem algo que precisa acontecer depois de uma determinada operação...algo que tem começo e fim definidos...então você pode simplesmente criar uma classe IDisposable que inicia a operação no construtor e depois termina no método Dispose.

Isso permite que você use a sintaxe using realmente interessante para denotar o início e o fim explícitos da referida operação.É também assim que funciona o material System.Transactions.

Você pode usar o namespace de alias por meio do exemplo a seguir:

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

Isso é chamado de usando a diretiva alias Como você pode ver, ele pode ser usado para ocultar referências de longa duração, caso você queira torná-lo óbvio em seu código o que você está se referindo, por exemplo,

LegacyEntities.Account

em vez de

CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account

ou simplesmente

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

Ao usar o ADO.NET, você pode usar a chave para coisas como seu objeto de conexão ou objeto de leitor.Dessa forma, quando o bloco de código for concluído, ele descartará automaticamente sua conexão.

"using" também pode ser usado para resolver conflitos de espaço de nomes.Ver http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ para um breve tutorial que escrevi sobre o assunto.

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

usando é usado quando você tem um recurso que deseja descartar após ter sido usado.

Por exemplo, se você alocar um recurso Arquivo e precisar usá-lo apenas em uma seção de código para ler ou escrever um pouco, usar é útil para descartar o recurso Arquivo assim que terminar.

O recurso usado precisa implementar IDisposable para funcionar corretamente.

Exemplo:

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

A palavra-chave using define o escopo do objeto e então descarta o objeto quando o escopo for concluído.Por exemplo.

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

Ver aqui para o artigo do MSDN sobre C# usando palavra-chave.

Não que seja muito importante, mas o uso também pode ser usado para alterar recursos rapidamente.Sim, descartável, conforme mencionado anteriormente, mas talvez você não queira especificamente que os recursos sejam incompatíveis com outros recursos durante o restante da execução.Então você deseja descartá-lo para que não interfira em outro lugar.

Graças aos comentários abaixo, vou limpar um pouco este post (não deveria ter usado as palavras ‘coleta de lixo’ na época, desculpas):
Quando você usa using, ele chamará o método Dispose() no objeto no final do escopo de using.Portanto, você pode ter um ótimo código de limpeza em seu método Dispose().
Um ponto aqui que, esperançosamente, talvez não seja marcado:Se você implementar IDisposable, certifique-se de chamar GC.SuppressFinalize() em sua implementação Dispose(), caso contrário, a coleta automática de lixo tentará aparecer e finalizá-la em algum momento, o que no mínimo seria um desperdício de recursos se você já Dispose()d dele.

Outro exemplo de uso razoável em que o objeto é descartado imediatamente:

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

Tudo que estiver fora das chaves é descartado, então é ótimo descartar seus objetos caso você não os esteja utilizando.Isso ocorre porque se você possui um objeto SqlDataAdapter e o está usando apenas uma vez no ciclo de vida da aplicação e está preenchendo apenas um conjunto de dados e não precisa mais dele, você pode usar o código:

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

A instrução using fornece um mecanismo conveniente para usar objetos IDisposable corretamente.Como regra, ao usar um objeto IDisposable, você deve declará-lo e instanciá-lo em uma instrução using.A instrução using chama o método Dispose no objeto da maneira correta e (quando você o usa como mostrado anteriormente) também faz com que o próprio objeto saia do escopo assim que Dispose for chamado.Dentro do bloco using, o objeto é somente leitura e não pode ser modificado ou reatribuído.

Isso vem de: aqui

Para mim o nome "using" é um pouco confuso, pois pode ser uma diretiva para importar um Namespace ou uma instrução (como a discutida aqui) para tratamento de erros.

Um nome diferente para tratamento de erros teria sido bom, e talvez um nome mais óbvio.

Também pode ser usado para criar escopos, por exemplo:

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

}

A instrução using diz ao .NET para liberar o objeto especificado no bloco using quando ele não for mais necessário.Portanto, você deve usar o bloco 'using' para classes que exigem limpeza, como System.IO Types.

Existem dois usos de palavras-chave em C#, como segue.

  1. como uma directiva

Geralmente usamos a palavra-chave using para adicionar namespaces em arquivos de classe e code-behind.Em seguida, disponibiliza todas as classes, interfaces e classes abstratas e seus métodos e propriedades na página atual.

Ex:

using System.IO;  
  1. como uma declaração

Esta é outra maneira de usar a palavra-chave using em C#.Ele desempenha um papel vital na melhoria do desempenho na coleta de lixo.A instrução using garante que Dispose() seja chamado mesmo se ocorrer uma exceção quando você estiver criando objetos e chamando métodos, propriedades e assim por diante.Dispose() é um método presente na interface IDisposable que ajuda a implementar a coleta de lixo customizada.Em outras palavras, se eu estiver realizando alguma operação de banco de dados (Inserir, Atualizar, Excluir), mas de alguma forma ocorrer uma exceção, aqui a instrução using fecha a conexão automaticamente.Não há necessidade de chamar explicitamente o método Close() da conexão.

Outro fator importante é que auxilia no pool de conexões.O pool de conexões no .NET ajuda a eliminar o fechamento de uma conexão de banco de dados várias vezes.Ele envia o objeto de conexão para um pool para uso futuro (próxima chamada ao banco de dados).Na próxima vez que uma conexão de banco de dados for chamada a partir do seu aplicativo, o pool de conexões buscará os objetos disponíveis no pool.Portanto, ajuda a melhorar o desempenho do aplicativo.Portanto, quando usamos a instrução using, o controlador envia o objeto para o pool de conexões automaticamente, não há necessidade de chamar explicitamente os métodos Close() e Dispose().

Você pode fazer o mesmo que a instrução using está fazendo usando o bloco try-catch e chamar Dispose() dentro do bloco finalmente explicitamente.Mas a instrução using faz as chamadas automaticamente para tornar o código mais limpo e elegante.Dentro do bloco using, o objeto é somente leitura e não pode ser modificado ou reatribuído.

Ex:

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

No código anterior não estou fechando nenhuma conexão, ela será fechada automaticamente.A instrução using chamará conn.Close() automaticamente devido à instrução using (using (SqlConnection conn = new SqlConnection(connString)) e o mesmo para um objeto SqlDataReader.E também se ocorrer alguma exceção a conexão será fechada automaticamente.

Para mais informações --> https://www.c-sharpcorner.com/UploadFile/manas1/usage-and-importance-of-using-in-C-Sharp472/

O Rhino zomba da sintaxe de reprodução de registro faz um uso interessante using.

Usar como uma instrução chama automaticamente a disposição no objeto especificado.O objeto deve implementar a interface IDisposable.É possível usar vários objetos em uma declaração, desde que sejam do mesmo tipo.

O CLR converte seu código em MSIL.E a instrução using é traduzida em um bloco try e finalmente.É assim que a instrução using é representada em IL.Uma instrução using é traduzida em três partes:aquisição, uso e descarte.O recurso é adquirido primeiro e, em seguida, o uso é incluído em uma instrução try com uma cláusula final.O objeto então é descartado na cláusula final.

Using Clause é usado para definir o escopo de uma variável específica.Por exemplo:

     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.
            }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top