O usuário kokos respondeu à maravilhosa pergunta Hidden Features of C # mencionando a using
palavra - chave. Você pode elaborar sobre isso? Quais são os usos de using
?
O usuário kokos respondeu à maravilhosa pergunta Hidden Features of C # mencionando a using
palavra - chave. Você pode elaborar sobre isso? Quais são os usos de using
?
Respostas:
O motivo da using
declaração é garantir que o objeto seja descartado assim que sair do escopo e não exija código explícito para garantir que isso aconteça.
Como em Entendendo a instrução 'using' em C # (codeproject) e Usando objetos que implementam IDisposable (microsoft) , o compilador C # 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();
}
}
O C # 8 apresenta uma nova sintaxe, denominada " usando declarações ":
Uma declaração using é uma declaração variável precedida pela palavra-chave using. Diz ao compilador que a variável que está sendo declarada deve ser descartada no final do escopo incluído.
Portanto, o código equivalente acima seria:
using var myRes = new MyResource();
myRes.DoSomething();
E quando o controle sair do escopo que contém (geralmente um método, mas também pode ser um bloco de código), myRes
será descartado.
using
garante que Dispose
seja chamado assim que você terminar o objeto.
MyRessource
é uma estrutura. Obviamente, não há teste de nulidade, mas também não há boxe para IDisposable
. Uma chamada virtual restrita é emitida.
using
, a variável criada dentro dele será somente leitura. Não há como conseguir isso para variáveis locais sem a using
instrução
Como muitas pessoas ainda fazem:
using (System.IO.StreamReader r = new System.IO.StreamReader(""))
using (System.IO.StreamReader r2 = new System.IO.StreamReader("")) {
//code
}
Eu 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
}
Isso SqlConnection
será fechado sem a necessidade de chamar explicitamente a .Close()
função, e isso acontecerá mesmo se uma exceção for lançada , sem a necessidade de um try
/ catch
/ finally
.
return
no meio do using
bloco.
usando, no sentido de
using (var foo = new Bar())
{
Baz();
}
Na verdade, é uma abreviação de um bloco try / finalmente. É equivalente ao código:
var foo = new Bar();
try
{
Baz();
}
finally
{
foo.Dispose();
}
Você observará, é claro, que o primeiro trecho é muito mais conciso que o segundo e também que existem 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 escopo que permite executar código arbitrário no método Dispose. Portanto, por exemplo, se você tivesse uma propriedade chamada IsWorking que sempre desejou definir como false após tentar executar uma operação, você faria o seguinte:
using (new Scope(() => IsWorking = false))
{
IsWorking = true;
MundaneYetDangerousWork();
}
Você pode ler mais sobre nossa solução e como a derivamos aqui .
A documentação da Microsoft afirma que o uso tem uma função dupla ( https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx ), como diretiva e em instruções . Como uma declaração , como foi indicado aqui em outras respostas, a palavra-chave é basicamente açúcar sintático para determinar um escopo para descartar um objeto IDisposable . Como diretiva , é rotineiramente usado para importar espaços e tipos de nomes. Também como diretiva, você pode criar aliases para namespaces e tipos, conforme apontado no livro "C # 5.0 Em poucas palavras: o guia definitivo" ( http://www.amazon.com/5-0-Nutshell-The- Referência-definitiva-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;
}
}
}
Isso é algo a ser adotado com sabedoria, pois o abuso dessa prática pode prejudicar a clareza do código. Há uma boa explicação sobre aliases de C #, também mencionando prós e contras, em DotNetPearls ( http://www.dotnetperls.com/using-alias ).
using
como uma ferramenta de pseudônimo. Me confunde ao ler o código - eu já sei que System.Collections
existe e tem a IEnumerable<T>
classe. Usar um apelido para chamá-lo de outra coisa ofusca-o para mim. Vejo using FooCollection = IEnumerable<Foo>
como uma maneira de fazer os desenvolvedores posteriores lerem o código e pensarem: "O que diabos é FooCollection
isso e por que não há uma classe para isso em algum lugar?" Eu nunca o uso e desencorajaria seu uso. Mas isso pode ser apenas eu.
Eu usei muito isso no passado para trabalhar com fluxos de entrada e saída. Você pode aninhá-los bem e remover muitos dos problemas em potencial com os quais você costuma se deparar (chamando automaticamente descarte). 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();
}
}
}
Apenas adicionando um pouco de algo que me surpreendeu não apareceu. A característica mais interessante de usar (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 do uso é ao instanciar um diálogo modal.
Using frm as new Form1
Form1.ShowDialog
' do stuff here
End Using
Em conclusão, quando você usa uma variável local de um tipo que implementa IDisposable
, sempre , sem exceção, use using
1 .
Se você usar IDisposable
variáveis não locais , sempre implemente o IDisposable
padrão .
Duas regras simples, sem exceção 1 . Prevenir o vazamento de recursos de outra forma é uma verdadeira dor no * ss.
1) : a única exceção é - quando você está lidando com exceções. Pode ser menos código para chamar Dispose
explicitamente no finally
bloco.
Você pode usar o espaço para nome alternativo usando o seguinte exemplo:
using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;
Isso é chamado de diretiva usando alias , como você pode ver, pode ser usado para ocultar referências prolongadas, caso você queira tornar óbvio em seu código o que você está se referindo, por exemplo
LegacyEntities.Account
ao invés de
CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account
ou simplesmente
Account // It is not obvious this is a legacy entity
Curiosamente, você também pode usar o padrão using / IDisposable para outras coisas interessantes (como o outro ponto do modo como o Rhino Mocks o usa). Basicamente, você pode tirar vantagem do fato de que o compilador sempre chamará .Dispose no objeto "usado". Se você tem algo que precisa acontecer após uma determinada operação ... algo que tenha um início e um fim definidos ... você pode simplesmente criar uma classe IDisposable que inicie a operação no construtor e termine no método Dispose.
Isso permite que você use a sintaxe realmente agradável para indicar o início e o fim explícitos da operação. É também assim que o material System.Transactions funciona.
Ao usar o ADO.NET, você pode usar o teclado 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 no espaço para nome. Veja 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
}
}
O uso é usado quando você tem um recurso que deseja descartar após o uso.
Por exemplo, se você alocar um recurso de arquivo e precisar usá-lo apenas em uma seção do código para um pouco de leitura ou gravação, usar é útil para descartar o recurso de arquivo assim que terminar.
O recurso que está sendo usado precisa implementar o 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 para o objeto e, em seguida, descarta o objeto quando o escopo estiver completo. Por exemplo.
using (Font font2 = new Font("Arial", 10.0f))
{
// use font2
}
Consulte aqui o artigo MSDN sobre o C # usando a palavra-chave.
Não que seja extremamente importante, mas o uso também pode ser usado para alterar recursos em tempo real. Sim, descartável, como mencionado anteriormente, mas talvez você não queira os recursos que não correspondem aos outros recursos durante o restante de sua execução. Então você quer descartá-lo para que não interfira em outro lugar.
Graças aos comentários abaixo, vou limpar um pouco essa postagem (eu não deveria ter usado as palavras 'coleta de lixo' no momento, desculpas):
Quando você usa, ele chama o método Dispose () no objeto no final do escopo do uso. Portanto, você pode ter um ótimo código de limpeza no seu método Dispose ().
Um marcador aqui que, esperançosamente, talvez consiga esse desmarcado: Se você implementar IDisposable, chame GC.SuppressFinalize () em sua implementação Dispose (), pois caso contrário a coleta de lixo automática tentará aparecer e finalizá-la em algum momento. point, que pelo menos seria um desperdício de recursos se você já tiver Dispose () d.
Outro exemplo de uso razoável no qual 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 fora dos colchetes é descartado; portanto, é ótimo descartar seus objetos se você não os estiver usando. Isso ocorre porque se você possui um objeto SqlDataAdapter e o está usando apenas uma vez no ciclo de vida do aplicativo, está preenchendo apenas um conjunto de dados e não precisa mais dele, 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 de conveniência para usar corretamente objetos IDisposable. Como regra, quando você usa um objeto IDisposable, você deve declarar e instancia-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 fique fora do escopo assim que Dispose é chamado. Dentro do bloco using, o objeto é somente leitura e não pode ser modificado ou reatribuído.
Isso vem de: aqui
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, uma vez que não é mais necessário. Portanto, você deve usar o bloco 'using' para classes que exigem limpeza após elas, como Tipos System.IO.
Existem dois usos da using
palavra - chave em C # da seguinte maneira.
Como diretiva
Geralmente, usamos a using
palavra-chave para adicionar namespaces nos arquivos code-behind e class. Em seguida, disponibiliza todas as classes, interfaces e classes abstratas e seus métodos e propriedades na página atual.
Exemplo:
using System.IO;
Como uma declaração
Essa é outra maneira de usar a using
palavra - chave em C #. Ela desempenha um papel vital na melhoria do desempenho na Coleta de Lixo.
A using
instrução garante que Dispose () seja chamado mesmo que ocorra uma exceção ao criar objetos e chamar métodos, propriedades e assim por diante. Dispose () é um método presente na interface IDisposable que ajuda a implementar a Coleta de Lixo personalizada. Em outras palavras, se estou executando alguma operação de banco de dados (Inserir, Atualizar, Excluir), mas de alguma forma ocorre uma exceção, então aqui a instrução using fecha a conexão automaticamente. Não é necessário chamar explicitamente o método Close () da conexão.
Outro fator importante é que ele ajuda no pool de conexões. O Pool de Conexão no .NET ajuda a eliminar o fechamento de uma conexão com o banco de dados várias vezes. Ele envia o objeto de conexão a um pool para uso futuro (próxima chamada ao banco de dados). Na próxima vez que uma conexão com o banco de dados for chamada do aplicativo, o pool de conexões buscará os objetos disponíveis no pool. Por isso, ajuda a melhorar o desempenho do aplicativo. Portanto, quando usamos a instrução using, o controlador envia o objeto para o conjunto de conexões automaticamente, não há necessidade de chamar os métodos Close () e Dispose () explicitamente.
Você pode fazer o mesmo que a instrução using usando o bloco try-catch e chamar o Dispose () dentro do bloco final 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.
Exemplo:
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; fechará automaticamente. A using
instrução chamará conn.Close () automaticamente devido à using
instrução ( using (SqlConnection conn = new SqlConnection(connString)
) e o mesmo para um objeto SqlDataReader. E também, se ocorrer alguma exceção, ela fechará a conexão automaticamente.
Para obter mais informações, consulte Uso e importância do uso em C # .
A sintaxe de reprodução de registros do Rhino Mocks faz um uso interessante de using
.
usar como uma declaração chama automaticamente a disposição no objeto especificado. O objeto deve implementar a interface IDisposable. É possível usar vários objetos em uma instrução, desde que sejam do mesmo tipo.
O CLR converte seu código em MSIL. E a instrução using é traduzida em uma tentativa e, finalmente, em um bloco. É assim que a instrução using é representada em IL. Uma declaração de uso é 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 finally. O objeto é descartado na cláusula finally.
A Cláusula Using é usada para definir o escopo da 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.
}