ユーザーkokosは、キーワードに言及することで、 C#の素晴らしい隠し機能の質問に答えました。using
それについて詳しく説明していただけますか?の用途は何using
ですか?
29 に答える
このステートメントの理由はusing
、オブジェクトがスコープ外になるとすぐに破棄されるようにするためであり、これを確実に行うための明示的なコードは必要ありません。
C# の 'using' ステートメントを理解する (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 (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
usingを使用して IDisposable を呼び出すことができます。別名タイプにも使用できます。
using (SqlConnection cnn = new SqlConnection()) { /* Code */}
using f1 = System.Windows.Forms.Form;
の意味で
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();
}
当社のソリューションとその導出方法について詳しくは、こちらをご覧ください。
Microsoft のドキュメントでは、usingにはディレクティブとステートメントの両方で二重の機能があると記載されています ( 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# エイリアスに関する適切な説明があり、長所と短所についても言及されています。
過去に、入力ストリームと出力ストリームを操作するためによく使用しました。それらをうまく入れ子にすることができ、(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のもう 1 つの優れた用途は、モーダル ダイアログをインスタンス化する場合です。
Using frm as new Form1
Form1.ShowDialog
' Do stuff here
End Using
次の例を使用して、エイリアス名前空間を利用できます。
using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;
ご覧のとおり、これはusing エイリアス ディレクティブと呼ばれます。コード内で何を参照しているのかを明確にしたい場合に、長々とした参照を非表示にするために使用できます。
LegacyEntities.Account
それ以外の
CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account
または単に
Account // It is not obvious this is a legacy entity
興味深いことに、using/IDisposable パターンを他の興味深い目的にも使用できます (Rhino Mocks が使用する方法の別のポイントなど)。基本的に、コンパイラは常に「使用済み」オブジェクトで .Dispose を呼び出すという事実を利用できます。特定の操作の後に発生する必要がある何かがある場合...明確な開始と終了があるもの...の場合、コンストラクターで操作を開始し、Dispose メソッドで終了する IDisposable クラスを作成するだけです。
これにより、非常に優れた using 構文を使用して、操作の明示的な開始と終了を示すことができます。これは System.Transactions の仕組みでもあります。
結論として、 を実装する型のローカル変数を使用する場合は、IDisposable
例外なく常にusing
1を使用してください。
非ローカルIDisposable
変数を使用する場合は、常にIDisposable
パターンを実装してください。
2 つの単純なルール、例外はありません1。それ以外の場合にリソース リークを防止することは、*ss にとって本当に苦痛です。
1) : 唯一の例外は – 例外を処理しているときです。その場合、ブロックDispose
内で明示的に呼び出すコードが少なくなる可能性があります。finally
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
}
}
ADO.NET を使用する場合、接続オブジェクトやリーダー オブジェクトなどにキーワークを使用できます。そうすれば、コード ブロックが完了すると、自動的に接続が破棄されます。
「using」は、名前空間の競合を解決するためにも使用できます。
このテーマについて私が書いた短いチュートリアルについては、http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/を参照してください。
usingは、使用後に破棄したいリソースがある場合に使用されます。
たとえば、ファイル リソースを割り当て、それをコードの 1 つのセクションで少しだけ読み書きするためにのみ使用する必要がある場合、 を使用すると、完了したらすぐにファイル リソースを破棄できます。
使用されているリソースは、適切に機能するために IDisposable を実装する必要があります。
例:
using (File file = new File (parameters))
{
// Code to do stuff with the file
}
私にとって、「using」という名前は少し紛らわしいです。これは、名前空間をインポートするためのディレクティブまたはエラー処理用のステートメント (ここで説明したものなど) になる可能性があるためです。
エラー処理に別の名前を付けた方がよかったかもしれません。
usingを使用すると、using のスコープの最後にあるオブジェクトで Dispose() メソッドが呼び出されます。したがって、Dispose() メソッドにかなりのクリーンアップ コードを含めることができます。
箇条書き:
IDisposable を実装する場合は、必ず Dispose() 実装で GC.SuppressFinalize() を呼び出してください。そうしないと、自動ガベージ コレクションが発生し、ある時点でそれをファイナライズしようとします。 'すでに Dispose()d しています。
中括弧の外側はすべて破棄されるため、オブジェクトを使用していない場合は破棄することをお勧めします。これは、SqlDataAdapter オブジェクトがあり、それをアプリケーション ライフ サイクルで 1 回だけ使用し、データセットを 1 つだけ埋めていて、もう必要ない場合は、次のコードを使用できるためです。
using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
// do stuff
} // here adapter_object is disposed automatically
オブジェクトがすぐに破棄される合理的な使用の別の例:
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);
}
}
usingキーワードは、オブジェクトのスコープを定義し、スコープが完了するとオブジェクトを破棄します。例えば。
using (Font font2 = new Font("Arial", 10.0f))
{
// Use font2
}
C# usingキーワードに関する MSDN の記事については、こちらを参照してください。
例のスコープを作成するためにも使用できます。
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ステートメントは、using ブロックで指定されたオブジェクトが不要になったら解放するように .NET に指示します。
そのため、 System.IO型など、後でクリーンアップする必要があるクラスには、'using' ブロックを使用する必要があります。
usingステートメントは、IDisposable オブジェクトを正しく使用するための便利なメカニズムを提供します。原則として、IDisposable オブジェクトを使用する場合は、using ステートメントで宣言してインスタンス化する必要があります。
usingステートメントは、オブジェクトの Dispose メソッドを正しい方法で呼び出します。また、(前に示したように使用すると) Dispose が呼び出されるとすぐに、オブジェクト自体がスコープ外になります。usingブロック内では、オブジェクトは読み取り専用であり、変更したり再割り当てしたりすることはできません。
これはここから来ています。
Rhino Mocks Record-playback Syntaxはを興味深い使い方をしていusing
ます。