ブロックを使用する際の変数(myform)が読み取り専用として扱われ、関数への参照として渡そうとするとコンパイラーがエラーを発生させるのはなぜですか。
サンプルコード:
using (Form myform = new Form)
{
myfunc(ref myform);
}
変数を使用してrefとして関数に渡すと、エラーが発生します。したがって、上記のコードはエラーを発生させます。
注:「readonly」キーワードは私の質問とは無関係です。
ブロックを使用する際の変数(myform)が読み取り専用として扱われ、関数への参照として渡そうとするとコンパイラーがエラーを発生させるのはなぜですか。
サンプルコード:
using (Form myform = new Form)
{
myfunc(ref myform);
}
変数を使用してrefとして関数に渡すと、エラーが発生します。したがって、上記のコードはエラーを発生させます。
注:「readonly」キーワードは私の質問とは無関係です。
私は今(時代遅れ?)スペック[1]を見ています。
15.13は、リソース取得部分で宣言する変数は読み取り専用であることを示しています。あれは:
var form = new Form1();
using (form) {
form = null;
}
動作しますが
using (var form = new Form1()) {
form = null;
}
そうではありません。これは質問の一部に答えます(つまり、なぜですか?仕様の一部であるためです。)が、これは本当に満足のいくものではないことを理解しています。しかし、なぜあなたはそれをしたいのですか?
編集:これについて考えた後、このルールの可能な説明を提供させてください:
あなたが持っている
using (var something = new Foo()) {
something = /* whatever */
}
コンパイラはこれを許可します。では、Fooが多くの管理されていないリソースを必要とする場合はどうなるでしょうか(おそらくそれが、そもそも使用using
したかった理由です)。ブロックを使用した後は、この参照にアクセスする方法がなくなります。再割り当てsomething
して自分で処理するのを忘れたため、破棄されませんでした。GCが実行されるという保証はまったくありません。またはいつ。隠されて隠されているリソースリークを作成しました。
最後の1つは、ヘンクのエリックリッパートのブログへのリンクに触発されたもので、これもまた、仕様を私たちに投げかけることになります。
フォームのusingステートメント
using(式)ステートメント
には同じ2つの可能な拡張がありますが、この場合、ResourceTypeは暗黙的に式のコンパイル時型であり、リソース変数は埋め込みステートメントではアクセスできず、見えません。
言い換えると:
var form = new Form1();
using (form) {
form = null;
}
これはに拡張されているため、動作します
var form = new Form1();
var invisibleThing = form;
try {
form = null;
} finally {
if (invisibleThing != null) ((IDisposable)invisibleThing).Dispose();
}
したがって、この場合、using
参照に影響を与えないという事実は、あなたから隠されているだけであり、前の場合とまったく同じです。
1:http://www.ecma-international.org/publications/standards/Ecma-334.htm
usingブロックの開始時にインスタンス化された変数を意味する場合、ブロックの終了時に破棄する必要があるため、読み取り専用になります。使用ブロックのポイントは、ガベージコレクターがそのジョブを実行するのを待つのではなく、予測可能な方法でリソースを破棄することです。
まず第一に、あなたの例では、ref
修飾子の理由はほとんどありません。
したがって、非常に理論的な質問をしているのですが、実際には問題になることはありません。
注釈付きのC#3マニュアルには説明がありません。
Eric Lippertは、usingステートメントのボクシングについての投稿(ではない)の主題に触れています。
私自身の刺し傷:
コンパイラーは、制御された変数を読み取り専用にします。このvarを書き込み可能のままにしておくと、さらに多くのワームの缶が開かれます。EricのBoxingの記事を参照してください。同様のルールがで囲まれた変数に適用されることに注意してくださいforeach()
。基本的に、これらの変数への書き込みは決して役に立たないので、コンパイラーがそれらを最大限に制御します。
readonlyはC#のキーワードです。コンストラクターの外部で値が変更されないようにする場合に便利です。
このキーワードは、大規模なプロジェクトにコードを提供していて、同僚が決して変更してはならない変数を変更しようとするのではないかと心配している場合に役立ちます。
編集:なぜ誰かが私の答えに反対票を投じたのか興味があります。反対票を投じた人は誰でも、私の答えが間違っているところを見せてくれませんか?ありがとう。