回答:
using
ステートメントの理由は、オブジェクトがスコープから外れるとすぐにオブジェクトが確実に破棄されるようにするためであり、これが発生することを確認するために明示的なコードを必要としません。
同様にC#(CodeProjectの)に声明」を使用しての理解とIDisposableを(Microsoft)を実装するオブジェクトを使用して、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宣言」という名前の新しい構文が導入されています。
using宣言は、usingキーワードに続く変数宣言です。これは、宣言されている変数を囲んでいるスコープの最後に配置する必要があることをコンパイラーに通知します。
したがって、上記と同等のコードは次のようになります。
using var myRes = new MyResource();
myRes.DoSomething();
コントロールが包含スコープ(通常はメソッドですが、コードブロックにすることもできます)を離れると、破棄myRes
されます。
using
必ずDispose
呼び出されます。
MyRessource
構造体の場合、生成されるコードは少し異なることに注意してください。明らかに、無効性のテストはありませんが、へのボクシングもありません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();
}
もちろん、最初のスニペットは2番目のスニペットよりもはるかに簡潔であり、例外がスローされた場合でもクリーンアップとして実行する必要のある多くの種類の処理があることに注意してください。このため、Disposeメソッドで任意のコードを実行できるようにするScopeと呼ばれるクラスを用意しました。したがって、たとえば、操作を実行した後に常にfalseに設定したいIsWorkingというプロパティがある場合は、次のようにします。
using (new Scope(() => IsWorking = false))
{
IsWorking = true;
MundaneYetDangerousWork();
}
私たちのソリューションとその導出方法については、こちらをご覧ください。
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(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ブロックを終了する方法が重要ではなく、常にオブジェクトを破棄することです。これには、返品と例外が含まれます。
using (var db = new DbContext())
{
if(db.State == State.Closed) throw new Exception("Database connection is closed.");
return db.Something.ToList();
}
例外がスローされるか、リストが返されるかは関係ありません。DbContextオブジェクトは常に破棄されます。
を使用するもう1つの優れた用途は、モーダルダイアログをインスタンス化するときです。
Using frm as new Form1
Form1.ShowDialog
' do stuff here
End Using
結論として、あなたは実装がその型のローカル変数を使用する場合IDisposable
、必ず、例外なく、使用using
1。
非ローカルIDisposable
変数を使用する場合は、常にIDisposable
パターンを実装してください。
2つの単純なルール、例外なし1。それ以外の方法でリソースリークを防止することは、* ssの大きな問題です。
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の動作方法でもあります。
ADO.NETを使用する場合、接続オブジェクトやリーダーオブジェクトなどにキーワークを使用できます。これにより、コードブロックが完了すると、接続が自動的に破棄されます。
「using」は、名前空間の競合を解決するためにも使用できます。このテーマについて書いた短いチュートリアルについては、http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/を参照してください。
usingは、使用後に破棄したいリソースがある場合に使用されます。
たとえば、Fileリソースを割り当て、コードの1つのセクションでそれを使用する必要がある場合は、使用すると、すぐにFileリソースを破棄できます。
使用されているリソースが正しく機能するには、IDisposableを実装する必要があります。
例:
using (File file = new File (parameters))
{
*code to do stuff with the file*
}
それが非常に重要であるというわけではありませんが、使用はその場でリソースを変更するためにも使用できます。はい、前述のように使い捨てですが、おそらく残りの実行中にリソースが他のリソースと一致しないようにしたくない場合があります。したがって、他の場所に干渉しないように廃棄する必要があります。
以下のコメントのおかげで、私はこの投稿を少し整理します(当時、「ガベージコレクション」という言葉は使用すべきではありませんでした。お詫び申し上げます):
usingを使用すると、オブジェクトのDispose()メソッドが呼び出されます使用範囲の最後。したがって、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オブジェクトがあり、アプリケーションライフサイクルで1回だけ使用していて、1つのデータセットのみを入力していて、それが不要になった場合は、コードを使用できるためです。
using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
// do stuff
} // here adapter_object is disposed automatically
usingステートメントは、IDisposableオブジェクトを正しく使用するための便利なメカニズムを提供します。原則として、IDisposableオブジェクトを使用する場合は、usingステートメントで宣言してインスタンス化する必要があります。usingステートメントは、オブジェクトのDisposeメソッドを正しい方法で呼び出します。また、(前述のように使用すると)Disposeが呼び出されるとすぐに、オブジェクト自体がスコープ外になります。usingブロック内では、オブジェクトは読み取り専用であり、変更または再割り当てすることはできません。
これは以下から来ています:here
また、例のスコープの作成にも使用できます。
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ステートメントは、usingブロックで指定されたオブジェクトが不要になったら解放するように.NETに指示します。したがって、System.IOタイプのように、後にクリーンアップが必要なクラスには「using」ブロックを使用する必要があります。
using
C#のキーワードには、次の2つの使用法があります。
指示として
通常、using
キーワードを使用して、分離コードファイルとクラスファイルに名前空間を追加します。次に、現在のページのすべてのクラス、インターフェース、抽象クラス、およびそれらのメソッドとプロパティを利用できるようにします。
例:
using System.IO;
ステートメントとして
これはusing
、C#でキーワードを使用する別の方法です。これは、ガベージコレクションのパフォーマンスを向上させる上で重要な役割を果たします。
このusing
ステートメントにより、オブジェクトを作成してメソッドやプロパティなどを呼び出すときに例外が発生した場合でも、Dispose()が確実に呼び出されます。Dispose()は、カスタムガベージコレクションの実装に役立つIDisposableインターフェイスにあるメソッドです。言い換えると、データベース操作(挿入、更新、削除)を実行しているのに、どういうわけか例外が発生した場合、usingステートメントは接続を自動的に閉じます。接続の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
ステートメントは、のために自動的に)(はconn.closeを呼び出しますusing
(ステートメントusing (SqlConnection conn = new SqlConnection(connString)
)とSqlDataReaderオブジェクトに同じ。また、例外が発生した場合は、接続を自動的に閉じます。
詳細については、「C#での使用と使用の重要性」を参照してください。
Rhinoのモック録音・再生構文の興味深い利用しますusing
。
ステートメントとして使用すると、指定したオブジェクトのdisposeが自動的に呼び出されます。オブジェクトはIDisposableインターフェイスを実装する必要があります。同じタイプのオブジェクトであれば、1つのステートメントで複数のオブジェクトを使用できます。
CLRはコードをMSILに変換します。そしてusingステートメントはtryに変換され、最終的にブロックされます。これは、ILでusingステートメントを表す方法です。usingステートメントは、取得、使用、および廃棄の3つの部分に変換されます。最初にリソースが取得され、次に使用法が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.
}