web-dev-qa-db-ja.com

C#で "using"を使用する方法

User kokosusingキーワードを言及することにより、素晴らしい C#の隠し機能 質問に回答しました。それについて詳しく説明できますか。 usingの用途は何ですか?

289
ubermonkey

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

多くの人がまだやっているので:

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

このようなこと:

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

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

このSqlConnectionは、.Close()関数を明示的に呼び出す必要なしに閉じられ、 例外がスローされたとしても try/catch/finallyを必要とせずにこれが起こります。

95
Joel Coehoorn

usingはIDisposableを呼び出すために使用できます。型のエイリアスにも使用できます。

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

という意味で

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

あなたは私たちの解決策と私たちがそれをどのように導いたかについてもっと読むことができます ここ

21
David Mitchell

Microsoftのドキュメントには、singには2つの関数( https://msdn.Microsoft.com/ja-jp/library/zhdeatwt.aspx )があります。 ディレクティブ および ステートメント内 ステートメント として、他の回答でも指摘したように、キーワードは基本的にIDisposableオブジェクトを配置する範囲を決定するための構文糖です。 ディレクティブ として、名前空間と型をインポートするために日常的に使用されています。 "C#5.0一言で言えば:The Definitive Guide"( http://www.Amazon)で指摘されているように、ディレクティブとして、名前空間と型に aliases を作成することもできます。 Joseph and Ben Albahari著、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( http://www.dotnetperls.com/using-alias )にも、長所と短所について言及しているC#エイリアスに関するナイスな説明があります。

10

入力ストリームと出力ストリームを操作するために、これまでよく使用してきました。あなたはうまくそれらを入れ子にすることができます、そしてそれはあなたが通常遭遇する潜在的な問題の多くを取り除きます(自動的に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();
                }
            }
        }
10
Sam Schutte

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

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

例外がスローされてもリストが返されてもかまいません。 DbContextオブジェクトは常に破棄されます。

8
Pluc

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

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using
6
Lucas

結論として、IDisposablename__、alwaysを実装する型のローカル変数を使用する場合は、例外なく、usingname__を使用します。1

非ローカルのIDisposablename__変数を使用する場合は、常にIDisposablename__パターン を実装してください。

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


1):唯一の例外は - 例外を扱っているときです。その場合、Disposename__ブロックでfinallyname__を明示的に呼び出す方がコードが少なくて済みます。

5
Konrad Rudolph

次の例のようにエイリアス名前空間を利用することができます。

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

お分かりのように、これはaliasディレクティブを使用と呼ばれます。参照しているものをコード内で明確にしたい場合は、長い参照を隠すために使用できます。

LegacyEntities.Account

の代わりに

CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account

あるいは単に

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

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

これにより、明示的な開始操作と終了操作を明示するために、本当にNiceを使用した構文を使用できます。これはSystem.Transactionsのものもどのように機能するかです。

4
Joel Martinez
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 
            }
    }
3
Shiraj Momin

ADO.NETを使用するときは、接続オブジェクトやリーダーオブジェクトなどのキーワークを使用できます。このようにして、コードブロックが完了すると自動的にあなたの接続を破棄します。

3
Joseph Daigle

"using"は、ネームスペースの競合を解決するためにも使用できます。このテーマについて書いた簡単なチュートリアルについては、 http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ を参照してください。

3
David Arno

Usingステートメントは、usingブロックで指定されたオブジェクトが不要になったら解放するように.NETに指示します。そのため、System.IO Typesのように、後処理を必要とするクラスには '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

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

エラー処理のための別の名前はNiceになっていたでしょう、そして多分どういうわけかもっと明白なものです。

1
Seb

例のスコープを作成するためにも使用できます。

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

}
1
Siamand Maroufi

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

1
Scot McPherson

Rhino Mocksの記録再生構文 は、usingの興味深い使い方です。

1
Gilligan

Usingステートメントは、IDisposableオブジェクトを正しく使用するための便利なメカニズムを提供します。原則として、IDisposableオブジェクトを使用するときは、usingステートメントで宣言してインスタンス化する必要があります。 usingステートメントは、正しい方法でオブジェクトのDisposeメソッドを呼び出します。また、(前述のように使用すると)Disposeメソッドが呼び出されると同時にオブジェクト自体がスコープ外になります。 usingブロック内では、オブジェクトは読み取り専用であり、変更や再割り当てはできません。

これは、から来ています: ここ

1
snowell

以下のコメントのおかげで、私はこの記事を少し整理します(当時は「ガベージコレクション」という言葉を使用してはいけませんでした、謝罪)。
usingを使うと、usingのスコープの最後にあるオブジェクトのDispose()メソッドを呼び出します。そのため、Dispose()メソッドにかなりのクリーンアップコードを含めることができます。
ここで箇条書きになっていると、マークされていない可能性があります。IDisposableを実装する場合は、Dispose()実装でGC.SuppressFinalize()を呼び出してください。ある時点でそれを完成させてください。すでにDispose()を実行しているのであれば、少なくともリソースの浪費になります。

1
Grank

中括弧の外側のものはすべて破棄されるので、使用していない場合は、オブジェクトを破棄することをお勧めします。これは、SqlDataAdapterオブジェクトがあり、それをアプリケーションライフサイクルの中で1回だけ使用していて、1つのデータセットだけを埋めていて、それが不要になった場合は、次のコードを使用できるためです。

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

Usingキーワードは、オブジェクトの有効範囲を定義し、有効範囲が完了するとそのオブジェクトを破棄します。例えば。

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

C#usingキーワードに関するMSDNの記事については、 here を参照してください。

1
David Basarab

オブジェクトがすぐに破棄される合理的な使用方法のもう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);
    }
}
1

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

たとえば、Fileリソースを割り当て、少しの読み書きのためにそれをコードの1セクションで使用するだけでよい場合は、usingを使用するとすぐにFileリソースを破棄できます。

使用されているリソースは、正しく機能するためにIDisposableを実装する必要があります。

例:

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