Sunny、ref、outは、マーシャリングのヒントとコンパイラーとの契約です。Refとoutは、COM日への持ち越しです。これは、ネットワークを介して/プロセス間で送信される場合のオブジェクトのマーシャリングのヒントです。
out契約_
void foo( out MyClass x)
- foo()は
x、戻る前に何かに設定されます。
xxfoo()が入力されたときは値がなく、設定する前に使用しようとするとコンパイラエラーが発生します。(割り当てられていない出力パラメーターxの使用)
ref契約_
void foo( ref MyClass x)
- refを使用すると、呼び出し元の参照を変更できます。
- xは割り当て可能である必要があります
- 中間変数に何かをキャストすることはできませんfoo(ref(object)something)
- xをプロパティにすることはできません
最後の2つのポイントの現実は、実際には参照が実際に何であるかを理解するときに意味をなさないため、あなたがやろうとしていることをやめさせる可能性があります。それを知りたい場合は、Jon Skeet(彼は本を書いた)に聞いてください。
refをマーシャリングする場合、戻り値に加えて、ref値も戻すように指示されています。マーシャリングするときは、メソッドが呼び出されたときにout値を送信する必要はありませんが、戻り値に加えてout値を戻すことを忘れないでください。
免責事項免責事項免責事項
他の人が指摘するように、何か怪しいことが起こっています。あなたが維持しているブルートフォースコードにはいくつかの微妙なバグがあり、偶然の一致によるコーディングに苦しんでいるようです。最善の解決策は、おそらく間接参照の別のレイヤーを追加することです。つまり、ラッパークラスのラッパーであり、コードベース全体にペッパーを付ける代わりに、乱雑なコードを1回だけ記述できる決定論的なクリーンアップを保証します。
それは言った..
代替案1
Refは、呼び出すすべてのタイプの(com)オブジェクトにオーバーロードを提供しない限り、このトリックを実行しません。
// need a remove method for each type.
void Remove( ref Com1 x ) { ...; x = null; }
void Remove( ref Con2 x ) { ...; x = null; }
void Remove( ref Com3 x ) { ...; x = null; }
// a generics version using ref.
void RemoveComRef<ComT>(ref ComT t) where ComT : class
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(t);
t = null;
}
Com1 c1 = new Com1();
Com2 c2 = new Com2();
Remove( ref c1 );
RemoveComRef(ref c2); // the generics version again.
代替案2
それを望まない場合は、Remove()メソッドからnullを返し、オブジェクトの型にキャストバックします。
class Remover
{
// .net 1.1 must cast if assigning
public static object Remove(object x)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(x);
return null;
}
// uses generics.
public static ComT RemoveCom<ComT>(ComT t) where ComT : class
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(t);
return null;
}
}
Com1 c1 = new Com1();
Com2 c2 = new Com2();
c1 = (Com1)Remover.Remove(c1); // no reliance on generics
c2 = Remover.RemoveCom(c2); // relies on generics
*比較のために汎用バージョンを追加しました。
上記のコードには、コードを見るときに、割り当てなしでRemove(x)の呼び出しを見ると、疑わしいものになるという効果があります(間違ったコードが間違って見えるようになります)。コードベースを介してGrepを実行し、割り当てが行われない場所でRemoveの呼び出しを探すこともできます。
免責事項-上記のすべては、参照を手動でnullに設定する必要があることを前提としていますが、これは(通常は)必要ありません。