274

사용자코코넛훌륭한 답변을C #의 숨겨진 기능언급하여 질문하다.using예어. 그것에 대해 자세히 설명해 주시겠습니까? 무엇의 용도인가?using?


  • RAII 관용구를 지원하는 것은 C #방식입니다.hackcraft.net/raii - Nemanja Trifunovic
  • IDispose 인터페이스를 구현 한 객체에 사용할 수 있습니다. using을 사용하면 해당 객체가 범위를 벗어날 때 Dispose 메서드가 호출됩니다. 예외가 발생하더라도 Dispose를 호출 할 수 있습니다. finally 절처럼 작동하고 Dispose를 실행합니다. - CharithJ

29 답변


417

그 이유는using선언문은 객체가 범위를 벗어나 자마자 폐기되도록 보장하며, 이러한 상황이 발생하지 않도록 명시적인 코드가 필요하지 않습니다.

에서와 같이C #에서 'using'문 이해하기, .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();
    }
}


  • 반드시 처분되는 물건의 문제는 아닙니다.바르게, 적시에 처분 될지 여부 등이 포함됩니다. 스트림 및 파일 핸들과 같은 관리되지 않는 리소스를 보유하는 IDisposable을 구현하는 개체는 가비지 수집 중에 Dispose가 호출되도록 보장하는 종료 자도 구현합니다. 문제는 GC가 비교적 오랜 시간 동안 발생하지 않을 수도 있다는 것입니다.using그걸 확인해.Dispose객체를 사용하면 호출됩니다. - John Saunders
  • 생성 된 코드는 다음과 같이 약간 다를 수 있습니다.MyRessource구조체입니다. 무효에 대한 테스트는 분명히 없지만 권투도하지 않습니다.IDisposable. 제한된 가상 호출이 발생합니다. - Romain Verdier
  • @paulwhit : 생성자가 위를 던지는 경우? - giorgim
  • 왜 사용하는 것을 언급하는 사람도 네임 스페이스를 가져 오는 데 사용되는 이유는 무엇입니까? - Kyle Delaney
  • 코드의 두 번째 버전을 직접 작성하는 경우 결과가 동일하지 않습니다. 귀하가using, 내부에 내장 된 변수는 읽기 전용입니다. 지역 변수에 대해이를 달성 할 방법이 없습니다.using성명서. - Massimiliano Kraus

115

많은 사람들이 아직도하기 때문에 :

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
  • @AgnelKurian No : "오류 CS1044 : for, using, fixed 또는 declaration 문에 하나 이상의 유형을 사용할 수 없습니다." - David Sykes
  • 이 질문에 어떻게 대답합니까? - Liam
  • 더 많은 변수를 인라이닝하는 것은 읽기가 어려워 보입니다. - Massimiliano Kraus
  • 사실 하나의 코드 블록 앞에 statemens를 사용하여 두 개를 쓸 수 있다는 사실을 알지 못했습니다. - kub1x

93

이런 것들 :

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

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

SqlConnection명시 적으로 전화 할 필요없이 닫힐 것입니다..Close()기능이 작동합니다.예외가 발생하더라도, 필요없이try/catch/finally.


  • & quot; 사용 & quot; 방법 안에, 그리고 나는 사용의 중간에 돌아갑니다. 무슨 문제라도 있습니까? - francisco_ssb
  • 문제 없습니다. 이 예에서는 연결이 닫혀있을지라도return의 중앙에서using블록. - Joel Coehoorn

29

using을 사용하여 IDisposable을 호출 할 수 있습니다. 별칭 유형에도 사용할 수 있습니다.

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


19

~을 사용하여

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

실제로 try / finally 블록의 줄임말입니다. 코드와 같습니다 :

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

물론 첫 번째 스 니펫은 두 번째 스 니펫보다 훨씬 간결하며 예외가 throw 된 경우에도 정리 작업을 수행 할 수있는 많은 종류가 있음을 알 수 있습니다. 이 때문에 우리는 Dispose 메서드에서 임의 코드를 실행할 수 있도록 Scope이라고 부르는 클래스를 만들었습니다. 예를 들어 IsWorking이라는 속성을 사용하여 작업을 수행하려고 시도한 후에 항상 false로 설정하려면 다음과 같이하십시오.

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

우리의 솔루션과 우리가 그것을 파생 한 방법에 대해 더 많이 읽을 수 있습니다.이리.


9

필자는 입력 및 출력 스트림을 사용하기 위해 과거에는 많이 사용했습니다. 그것들을 멋지게 겹치게 할 수 있으며, 일반적으로 (자동으로 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();
                }
            }
        }


9

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 (DotNetPearls에서 찬반 양론을 언급하면서 C # 별칭에 대한 좋은 설명이 있습니다.http://www.dotnetperls.com/using-alias).


  • 거짓말하지 마라 : 나미움사용using별칭 도구로. 코드를 읽을 때 혼란 스럽습니다. 이미 알고 있습니다.System.Collections존재하며IEnumerable<T>수업. 별칭을 사용하여 다른 것을 호출하면 나를 혼란스럽게 만듭니다. 내가 참조using FooCollection = IEnumerable<Foo>나중에 개발자가 코드를 읽고 "어떻게 도대체 무엇입니까?"라고 생각하는 방법입니다.FooCollection어딘가에서 클래스를 찾을 수없는 이유는 무엇입니까? & quot; 나는 결코 그것을 사용하지 않으며 그것의 사용을 낙담시킬 것이다. 하지만 그건 나일지도 몰라. - Ari Roth
  • 부록 : 대리인을 정의 할 때 사용하는 예제처럼 가끔씩 사용할 수 있다고 인정합니다. 그러나 나는 상대적으로 희귀하다고 주장한다. - Ari Roth

7

내가 놀랐던 작은 물건을 추가하는 것만이 생기지 않았다. 가장 흥미로운 기능은 (내 의견으로는) 사용하는 블록을 종료하는 방법이 없기 때문에 항상 객체를 처리한다는 것입니다. 여기에는 반품 및 예외가 포함됩니다.

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

예외가 던져 지거나 목록이 반환되는지 여부는 중요하지 않습니다. DbContext 개체는 항상 삭제됩니다.


4

결론적으로, 당신이 구현하는 타입의 지역 변수를 사용할 때IDisposable,항상, 예외없이, 사용using1.

로컬이 아닌IDisposable변수항상~을 구현하다IDisposable무늬.

두 가지 간단한 규칙, 예외 없음1. 그렇지 않으면 리소스 유출을 막는 것이 * ss의 진정한 고통입니다.


1): 유일한 예외는 예외를 처리 할 때입니다. 그런 다음 적은 코드로 호출 할 수 있습니다.Dispose명시 적으로finally블록.


4

사용의 또 다른 큰 용도는 모달 대화 상자를 인스턴스화하는 것입니다.

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using



3

흥미롭게도, Rhino Mock이 사용하는 다른 지점과 같이 재미있는 다른 것들에 대해 using / IDisposable 패턴을 사용할 수도 있습니다. 기본적으로, 당신은 컴파일러가항상"used"객체에 대해 .Dispose를 호출하십시오. 특정 작업 후에 발생해야하는 작업이있는 경우 ... 시작과 끝이 확실한 작업 ... 그러면 IDisposable 클래스를 만들어 생성자에서 작업을 시작한 다음 Dispose 메서드에서 작업을 완료 할 수 있습니다.

이렇게하면 실제로 사용하기 쉬운 구문을 사용하여 해당 작업의 명시적인 시작과 끝을 나타낼 수 있습니다. 이것은 System.Transactions 작업이 작동하는 방법이기도합니다.


3

다음 예제와 같이 별칭 네임 스페이스를 사용할 수 있습니다.

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


2

ADO.NET을 사용할 때 연결 개체 또는 판독기 개체와 같은 요소에 대한 핵심 작업을 사용할 수 있습니다. 이렇게하면 코드 블록이 완료되면 연결이 자동으로 삭제됩니다.


  • 코드 블록을 완료하지 않아도된다고 덧붙일 것입니다. using 블록은 처리되지 않은 예외가 발생하더라도 리소스를 삭제합니다. - harpo
  • 좀 더 명확히하기 위해 가비지 수집기가 원하는 시점에 가비지 수집기가 할당을 처리하는지 확인하는 방법입니다.그것에 싶어. - moswald

2

"using"을 사용하여 이름 공간 충돌을 해결할 수도 있습니다. 만나다http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/짧은 자습서를 위해 나는 주제에 썼다.


2

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


1

using 문은 IDisposable 개체를 올바르게 사용하기위한 편리한 메커니즘을 제공합니다. 일반적으로 IDisposable 개체를 사용할 때는 using 문에서 선언하고 인스턴스화해야합니다. using 문은 올바른 방법으로 개체의 Dispose 메서드를 호출하고, 앞에서 설명한대로 사용하면 Dispose가 호출되자 마자 개체 자체가 범위를 벗어납니다. using 블록 내에서 객체는 읽기 전용이므로 수정하거나 다시 할당 할 수 없습니다.

이것은 다음에서 유래합니다 :이리


1

다음과 같이 C #에서 keyword를 두 가지 용도로 사용합니다.

  1. 지시어로서

일반적으로 using 키워드를 사용하여 코드 숨김 파일과 클래스 파일에 네임 스페이스를 추가합니다. 그런 다음 현재 페이지의 모든 클래스, 인터페이스 및 추상 클래스와 메소드 및 속성을 사용할 수있게합니다.

전의:

using System.IO;  
  1. 성명서로

이것은 C #에서 using 키워드를 사용하는 또 다른 방법입니다. 가비지 콜렉션의 성능을 향상시키는 데 중요한 역할을합니다. using 문은 객체를 만들고 메서드, 속성 등을 호출 할 때 예외가 발생하더라도 Dispose ()가 호출되도록합니다. Dispose ()는 사용자 지정 가비지 수집을 구현하는 데 도움이되는 IDisposable 인터페이스에있는 메서드입니다. 즉, 일부 데이터베이스 작업 (삽입, 업데이트, 삭제)을하고 있지만 어떻게 든 예외가 발생하면 여기서 using 문은 자동으로 연결을 닫습니다. Close () 메서드를 명시 적으로 호출 할 필요가 없습니다.

또 다른 중요한 요소는 연결 풀링에서 도움이된다는 것입니다. .NET의 연결 풀링은 여러 번 데이터베이스 연결을 닫지 않아도됩니다. 나중에 사용할 수 있도록 연결 개체를 풀에 보냅니다 (다음 데이터베이스 호출). 다음 번에 응용 프로그램에서 데이터베이스 연결이 호출되면 연결 풀은 풀에서 사용 가능한 개체를 반입합니다. 따라서 응용 프로그램의 성능을 향상시키는 데 도움이됩니다. 따라서 using 문을 사용하면 컨트롤러가 객체를 연결 풀로 자동 전송하므로 명시 적으로 Close () 및 Dispose () 메서드를 호출 할 필요가 없습니다.

try-catch 블록을 사용하여 using 문이 수행하는 것과 동일한 작업을 수행하고 finally 블록 내에서 Dispose ()를 명시 적으로 호출 할 수 있습니다. 그러나 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 문은 using 문 ((SqlConnection conn = new SqlConnection (connString))을 사용하여 SqlDataReader 개체에 대해 자동으로 conn.Close ()를 호출하고 예외가 발생하면 자동으로 연결을 닫습니다.

추가 정보 ->https://www.c-sharpcorner.com/UploadFile/manas1/usage-and-importance-of-using-in-C-Sharp472/


1

그만큼Rhino 모의 레코드 재생 구문재미있는 사용법을 만든다.using.


  • Playback과 Verify를 호출하는 것과 기본적으로 동일한 것은 Dispose () 메소드에서 수행합니다. - George Mauer

0

~을 사용하여사용 후 폐기하려는 리소스가있을 때 사용됩니다.

예를 들어 File 리소스를 할당하고 약간의 읽기 또는 쓰기를 위해 코드의 한 섹션에서만 사용해야하는 경우 사용하면 완료되면 File 리소스를 삭제하는 데 유용합니다.

사용되는 리소스가 제대로 작동하려면 IDisposable을 구현해야합니다.

예:

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


0

using 키워드는 객체의 범위를 정의한 다음 범위가 완료 될 때 객체를 삭제합니다. 예를 들어.

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

만나다이리C # using 키워드에 대한 MSDN 기사.


0

그것이 매우 중요하지는 않지만, 사용은 리소스를 즉각적으로 변경할 수 있습니다. 예, 이전에 언급했듯이 일회용이지만 나머지 실행 중에 다른 리소스와 일치하지 않는 리소스는 원하지 않을 수 있습니다. 그래서 다른 곳에 간섭하지 않도록 처분하고 싶습니다.


0

아래의 설명에 감사 드리며, 나는이 글을 조금 정리할 것입니다 (나는 그 때 쓰레기 수집이라는 단어를 사용해서는 안됩니다, 사과).

using을 사용하면 사용 범위 끝의 개체에서 Dispose () 메서드가 호출됩니다. 따라서 Dispose () 메서드에서 훌륭한 정리 코드를 만들 수 있습니다.

글 머리 기호는 여기 아마 희망이 어쩌면이 un-markeddown 얻을 것이다 : IDisposable 구현하면 자동으로 가비지 수집 함께오고 시도 할 일부 () 구현하려고합니다 Dispose () 구현 GC.SuppressFinalize () 호출해야합니다. 당신이 이미 Dispose ()했다면 최소한의 자원 낭비가 될 것입니다.


  • GC에는 아무런 영향을 미치지 않습니다. - Jason Diller
  • 간접적 인 효과가 있습니다. 개체를 명시 적으로 삭제 했으므로 완료 할 필요가 없으므로 이전 GC 일 수 있습니다. - Kent Boogaart

0

객체가 즉시 폐기되는 합리적인 사용의 또 다른 예 :

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


0

중괄호 바깥 쪽은 모두 폐기되므로 사용하지 않을 경우 개체를 처분하는 것이 좋습니다. 이는 SqlDataAdapter 개체가 있고 응용 프로그램 수명주기에 한 번만 사용하고 하나의 데이터 집합 만 채우고 더 이상 필요하지 않으면 다음 코드를 사용할 수 있기 때문입니다.

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


0

나에게 "using"이라는 이름은 조금 혼란 스럽다. 왜냐하면 오류 처리를 위해 Namespace이나 문장 (여기에서 논의 된 것과 같은)을 임포트하라는 지시어가있을 수 있기 때문이다.

오류 처리에 대한 다른 이름은 좋았을 것입니다. 그리고 아마도 더 명백한 오류 일 수도 있습니다.


0

예를 들어 스코프를 생성하는 데에도 사용할 수 있습니다.

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

}


0

using 문은 더 이상 필요하지 않으면 using 블록에 지정된 객체를 해제하도록 .NET에 지시합니다. 따라서 System.IO Types와 같이 클래스를 정리해야하는 클래스의 경우 'using'블록을 사용해야합니다.


-1

명령문으로 사용하면 지정된 위치의 dispose가 자동으로 호출됩니다.   목적. 개체는 IDisposable 인터페이스를 구현해야합니다. 그것은   한 문장 내에서 여러 객체를 사용할 수 있습니다.   같은 유형의

CLR은 코드를 MSIL로 변환합니다. using 문은 try 및 finally 블록으로 변환됩니다. 이것은 using 문이 IL에서 어떻게 표현되는지를 나타냅니다. using 문은 획득, 사용 및 폐기라는 세 부분으로 번역됩니다. 리소스가 처음 획득되면 사용법은 finally 절이있는 try 문으로 묶입니다. 그런 다음 객체는 finally 절에 배치됩니다.


-2

절 사용은 특정 변수의 범위를 정의하는 데 사용됩니다. 예 :

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

연결된 질문


관련된 질문

최근 질문