답변:
using
명령문 의 이유 는 오브젝트가 범위를 벗어나 자마자 처리되도록하기위한 것이며 명시적인 코드가 필요하지 않습니다.
마찬가지로 C #을 (CodeProject의)에서 '사용'문을 이해 하고 는 IDisposable (마이크로 소프트) 구현하는 객체 사용 , C # 컴파일러의 변환을
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();
}
}
C # 8에는 " using declarations " 라는 새로운 구문이 도입되었습니다 .
using 선언은 using 키워드가 앞에 오는 변수 선언입니다. 선언 된 변수가 둘러싸는 범위의 끝에 배치되어야한다고 컴파일러에 알려줍니다.
따라서 위와 동등한 코드는 다음과 같습니다.
using var myRes = new MyResource();
myRes.DoSomething();
그리고 제어가 포함 범위를 벗어나면 (보통 방법이지만 코드 블록 일 수도 있음) myRes
폐기됩니다.
using
있는지 확인합니다 Dispose
당신이 객체를 통해있어 한 번이라고합니다.
MyRessource
구조체 일 때 약간 다릅니다 . 분명히 nullity에 대한 테스트는 없지만에 대한 권투도 없습니다 IDisposable
. 제한된 가상 통화가 발생합니다.
using
그 안에 내장 된 변수는 읽기 전용입니다. using
명령문 없이 로컬 변수에 대해서는이를 수행 할 방법이 없습니다 .
많은 사람들이 여전히하기 때문에 :
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
return
중간에서 연결하더라도 연결이 계속 닫힙니다 using
.
의 의미에서
using (var foo = new Bar())
{
Baz();
}
실제로 try / finally 블록의 속기입니다. 코드와 같습니다.
var foo = new Bar();
try
{
Baz();
}
finally
{
foo.Dispose();
}
물론 첫 번째 스 니펫은 두 번째 스 니펫보다 훨씬 간결하며 예외가 발생하더라도 정리로 수행 할 수있는 작업이 많이 있습니다. 이 때문에 Dispose 메서드에서 임의의 코드를 실행할 수있는 Scope라는 클래스가 만들어졌습니다. 예를 들어, 작업을 수행하려고 시도한 후 항상 false로 설정하려는 IsWorking이라는 속성이있는 경우 다음과 같이합니다.
using (new Scope(() => IsWorking = false))
{
IsWorking = true;
MundaneYetDangerousWork();
}
우리의 솔루션에 대한 자세한 내용과 여기 에서 우리가 그 솔루션을 도출 한 방법에 대해 읽을 수 있습니다 .
Microsoft 설명서에는 using 을 지시문 및 명령문 으로 두 가지 기능 ( https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx ) 이 있다고 명시되어 있습니다. A와 문 은 다른 답변에서 여기에서 지적 된 바와 같이, 키워드는 기본적으로 처분 할 수있는 범위를 결정하는 문법 설탕이다 는 IDisposable 개체를. A와 지시어 , 그것은 정기적으로 수입 네임 스페이스 및 유형에 사용됩니다. 또한 지시자로, 당신은 만들 수 있습니다 별칭 이 책에서 지적 밖으로로서, 네임 스페이스 및 유형을 "간단히 말해서 C # 5.0 : 확실한 가이드"( http://www.amazon.com/5-0-Nutshell-The-을 확정 참조 전자 책 / 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 ( http://www.dotnetperls.com/using-alias ) 에는 장단점을 언급하는 C # 별칭에 대한 좋은 설명이 있습니다 .
using
. 코드를 읽을 때 혼란 스럽습니다. 이미 System.Collections
존재하고 IEnumerable<T>
클래스 가 있음을 이미 알고 있습니다 . 별명을 사용하여 그것을 다른 것으로 부르면 나를 위해 난독 화합니다. 내가 볼 using FooCollection = IEnumerable<Foo>
나중에 개발자가 코드를 읽고, 생각하게하는 방법으로 "지옥이 무엇 FooCollection
이며 왜위한 클래스는 곳이 없다?" 나는 그것을 사용하지 않으며 사용을 권장하지 않습니다. 그러나 그것은 단지 나일지도 모른다.
과거에는 입력 및 출력 스트림으로 작업하는 데 많이 사용했습니다. 그것들을 멋지게 중첩시킬 수 있으며 일반적으로 (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();
}
}
}
내가 놀란 작은 것을 추가하는 것은 나타나지 않았습니다. (내 의견으로는) 사용의 가장 흥미로운 특징은 사용 블록을 종료하는 방법이 중요하지 않으며 항상 객체를 처분한다는 것입니다. 여기에는 반품 및 예외가 포함됩니다.
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
, 항상 예외없이 사용 using
1 .
비 로컬 IDisposable
변수 를 사용하는 경우 항상 IDisposable
패턴을 구현하십시오 .
두 가지 간단한 규칙, 예외 없음 1 . 그렇지 않으면 리소스 누출을 방지하는 것이 실제로 고통 스럽습니다.
1) : 예외를 처리 할 때는 예외입니다. 그러면 블록 Dispose
에서 명시 적으로 호출하는 코드가 줄어 듭니다 finally
.
다음 예제를 통해 별명 네임 스페이스를 사용할 수 있습니다.
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
흥미롭게도 Rhino Mocks가 사용하는 방식과 같은 다른 흥미로운 것들에 대해 using / IDisposable 패턴을 사용할 수도 있습니다. 기본적으로 컴파일러는 항상 "사용 된"객체에서 .Dispose를 호출 한다는 사실을 이용할 수 있습니다 . 특정 작업 후 시작해야하는 작업 (확실한 시작 및 종료 기능이있는 작업)이있는 경우 생성자에서 작업을 시작한 다음 Dispose 메서드에서 완료하는 IDisposable 클래스를 만들 수 있습니다.
이를 통해 정말 멋진 구문을 사용하여 해당 작업의 명시 적 시작과 끝을 나타낼 수 있습니다. 이것은 System.Transactions 기능도 작동합니다.
"사용"을 사용하여 네임 스페이스 충돌을 해결할 수도 있습니다. 내가 주제에 대해 쓴 짧은 튜토리얼 은 http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ 를 참조 하십시오 .
매우 중요하지는 않지만 사용은 자원을 즉시 변경하는 데 사용될 수도 있습니다. 예, 앞에서 언급했듯이 일회용이지만, 특히 실행하는 동안 다른 리소스와 일치하지 않는 리소스를 원하지 않을 수 있습니다. 따라서 다른 곳을 방해하지 않도록 폐기하십시오.
(사과를 나는 시간에 단어 '가비지 수집을'사용 안) 아래의 의견 덕분에, 나는 조금 업이 게시물을 정리합니다 :
당신이 사용하는 사용하는 경우, 그것은 개체의 폐기 () 메소드를 호출 사용 범위의 끝에서. 따라서 Dispose () 메서드에 상당히 훌륭한 정리 코드가있을 수 있습니다.
IDisposable을 구현하는 경우 Dispose () 구현에서 GC.SuppressFinalize ()를 호출해야합니다. 적어도 이미 Dispose () d 한 경우 리소스 낭비가 될 것입니다.
물체가 즉시 폐기되는 합리적인 사용의 또 다른 예 :
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
예를 들어 범위를 만드는 데 사용할 수도 있습니다.
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
C # 에서 키워드는 다음과 같이 두 가지 용도 로 사용됩니다.
지침으로
일반적으로 using
키워드를 사용하여 코드 숨김 및 클래스 파일에 네임 스페이스를 추가합니다. 그런 다음 현재 페이지에서 모든 클래스, 인터페이스 및 추상 클래스와 해당 메소드 및 특성을 사용할 수 있습니다.
예:
using System.IO;
성명서
using
C # 에서 키워드 를 사용하는 또 다른 방법 입니다. 가비지 콜렉션에서 성능을 향상시키는 데 중요한 역할을합니다.
이 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
문 인해 자동) conn.Close을 (호출 using
문 ( using (SqlConnection conn = new SqlConnection(connString)
)와 SqlDataReader 개체 개체에 대한 동일. 또한 예외가 발생하면 연결이 자동으로 닫힙니다.
자세한 내용 은 C #에서 사용 및 사용의 중요성을 참조하십시오 .
코뿔소 모의 객체 기록 재생 구문 의 흥미를 사용합니다 using
.
명령문으로 사용하면 지정된 오브젝트에서 처분을 자동으로 호출합니다. 객체는 IDisposable 인터페이스를 구현해야합니다. 동일한 유형 인 한 명령문에서 여러 오브젝트를 사용할 수 있습니다.
CLR은 코드를 MSIL로 변환합니다. using 문은 try 및 finally 블록으로 변환됩니다. 이것이 using 문이 IL에서 표현되는 방식입니다. using 문은 획득, 사용 및 폐기의 세 부분으로 번역됩니다. 자원을 먼저 확보 한 후 사용법은 finally 절과 함께 try 문으로 묶습니다. 그런 다음 객체는 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.
}