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
  • usingが名前空間のインポートにも使用されていると言及している人がいないのはなぜですか。 - Kyle Delaney
  • あなたが直接コードの2番目のバージョンを書いた場合、結果は同じではないことに注意してください。あなたが使用する場合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
  • 実際には、1つのコードブロックの前にstatemensを使用して2つ記述することができることを知りませんでした(毎回それらをネストすることになります)。 - 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


  • " using"を使用している場合はどうなりますか。メソッド内で、使用中に戻ります。何か問題ある? - 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();
}

もちろん、最初のスニペットは2番目のスニペットよりもはるかに簡潔で、例外がスローされた場合でもクリーンアップとして実行したいことがたくさんあることに気付くでしょう。このため、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)として指令とで。としてステートメント他の回答でも指摘されているように、キーワードは基本的に構文の糖であり、使い捨てオブジェクトとして指令名前空間と型をインポートするために日常的に使用されています。ディレクティブとしても作成できます。エイリアス"C#5.0一言で言えば:The Definitive Guide"で指摘されているように、名前空間と型についてhttp://www.amazon.com/5-0-Nutshell-The-Definitive-Reference-ebook/dp/B008E6I1K8)、ジョセフとベンAlbahariによって。一例です。

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


  • うそをつくつもりはない:私は嫌いの用法usingエイリアスツールとして。コードを読むときそれは私を混乱させる - 私はすでにそれを知っているSystem.Collections存在しているIEnumerable<T>クラス。エイリアスを使用して別の名前にすると、わかりにくくなります。そうですかusing FooCollection = IEnumerable<Foo>後の開発者にコードを読んでもらい、「地獄は何ですか。FooCollectionまた、そのクラスがどこかにないのはなぜですか。私はそれを使うことは決してなく、その使用をお勧めしません。しかし、それは私だけかもしれません。 - Ari Roth
  • 補遺:あなたがデリゲートを定義するのに使っているあなたの例のように、時折それを使うことがあるかもしれないと私は認めるでしょう。しかし、これらは比較的まれです。 - Ari Roth

7

ちょっと驚いたことを少し追加しても思いつかなかった。 usingの最も興味深い機能(私の意見では)は、usingブロックを終了する方法に問題がないということです。常にオブジェクトを破棄することになります。これには返品と例外が含まれます。

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パターン

2つの単純な規則、例外なし1。そうでなければリソースリークを防ぐことは* ssの本当の苦痛です。


1):唯一の例外は - 例外を扱っているときです。そうすると呼び出すコードが少なくなるかもDispose明示的にfinallyブロック。


4

usingのもう1つの優れた用途は、モーダルダイアログをインスタンス化するときです。

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using


  • frm.ShowDialogを意味しましたか? - DaveInCaz

3

興味深いことに、他の面白いことにRhino Mocksが使う他の方法などでusing / IDisposableパターンを使うこともできます。基本的には、コンパイラが常に"used"オブジェクトに.Disposeを呼び出します。特定の操作の後に実行する必要があるもの、つまり開始と終了が明確なものがある場合は、単純にコンストラクタで操作を開始し、Disposeメソッドで終了するIDisposableクラスを作成できます。

これにより、上記の操作の明示的な開始と終了を示すために、本当に便利なusing構文を使用できます。これは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#でキーワードを使用する方法は2つあります。

  1. 指令として

通常、usingキーワードを使用して、コードビハインドファイルとクラスファイルに名前空間を追加します。その後、現在のページですべてのクラス、インタフェース、抽象クラス、およびそれらのメソッドとプロパティを利用可能にします。

例:

using System.IO;  
  1. 文として

これはC#でusingキーワードを使用するもう1つの方法です。これは、ガベージコレクションのパフォーマンスを向上させる上で重要な役割を果たします。 usingステートメントを使用すると、オブジェクトを作成してメソッドやプロパティなどを呼び出すときに例外が発生した場合でも、Dispose()が確実に呼び出されるようになります。 Dispose()は、カスタムのガベージコレクションを実装するのに役立つIDisposableインターフェイスに存在するメソッドです。言い換えれば、私が何らかのデータベース操作(Insert、Update、Delete)を実行しているのに、どういうわけか例外が発生した場合、usingステートメントは自動的に接続を閉じます。 connection Close()メソッドを明示的に呼び出す必要はありません。

もう1つの重要な要素は、それが接続プーリングに役立つということです。 .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ステートメント(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 Mocksの記録再生構文の面白い使い方をするusing


  • それは基本的にPlaybackを呼び出してそれがDispose()メソッドでそれをすることをすべて確認することと同じです - George Mauer

0

使う使用後に破棄したいリソースがある場合に使用されます。

たとえば、Fileリソースを割り当て、少しの読み書きのためにそれをコードの1つのセクションで使用するだけの場合は、usingを使用するとすぐに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

それが非常に重要であるというわけではありませんが、usingを使用してリソースをその場で変更することもできます。はい、前述のように使い捨てですが、実行の残りの部分で他のリソースとリソースが一致しないようにする必要があります。だからあなたはそれが他の場所に干渉しないようにそれを処分したいのです。


0

以下のコメントのおかげで、私はこの記事を少し整理します(当時は「ガベージコレクション」という言葉は使用してはいけませんでした、謝罪)。

usingを使うと、usingのスコープの最後にあるオブジェクトのDispose()メソッドを呼び出します。そのため、Dispose()メソッドにかなりのクリーンアップコードを含めることができます。

ここで重要な点は、マーク付けされていない可能性があることです。IDisposableを実装する場合は、Dispose()実装でGC.SuppressFinalize()を呼び出すようにしてください。これは、すでにDispose()dを実行している場合は、少なくともリソースの浪費になります。


  • GCには影響しません。 - Jason Diller
  • 間接的な効果があります。オブジェクトは明示的に破棄されているため、ファイナライズを必要とせず、したがってGCを早くすることができます。 - Kent Boogaart

0

オブジェクトがすぐに破棄される合理的な使用方法のもう1つの例:

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オブジェクトがあり、それをアプリケーションライフサイクルの中で1回だけ使用していて、1つのデータセットだけを埋めていて、それが不要になった場合は、次のコードを使用できるためです。

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


0

私にとっては "using"という名前は少し混乱を招くものです。なぜならこれは名前空間をインポートするためのディレクティブや(ここで説明したような)ステートメントをエラー処理のために使うことができるからです。

エラー処理のための別の名前は素晴らしかったでしょう、そして多分どういうわけかより明白なものであるかもしれません。


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

ステートメントとして使用すると、自動的に指定したオブジェクトの処理が呼び出されます。   オブジェクトオブジェクトはIDisposableインターフェイスを実装する必要があります。それは   1つのステートメントで複数のオブジェクトを使用することは可能です。   同じタイプです。

CLRはあなたのコードをMSILに変換します。そしてusingステートメントはtryに変換され、最後にブロックされます。これがusingステートメントがILでどのように表されるかです。 usingステートメントは、取得、使用、および廃棄の3つの部分に翻訳されています。リソースが最初に取得され、次に使用法がfinally節を含むtry文に囲まれます。その後、オブジェクトはfinally節に配置されます。


-2

using句は、特定の変数のスコープを定義するために使用されます。 例えば:

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

リンクされた質問


関連する質問

最近の質問