System.Runtime.InteropServices
の下に<Out()>
の属性が存在します。 しかし、それは何ですか?私はあなたの答えのベースとして次の例を使うことができたらうれしいです。<Out()>属性。有用な目的は何ですか?
Shared Sub Add(ByVal x As Integer, ByVal y As Integer, <Out()> ByRef Result As Integer)
Result = x + y
End Sub
System.Runtime.InteropServices
の下に<Out()>
の属性が存在します。 しかし、それは何ですか?私はあなたの答えのベースとして次の例を使うことができたらうれしいです。<Out()>属性。有用な目的は何ですか?
Shared Sub Add(ByVal x As Integer, ByVal y As Integer, <Out()> ByRef Result As Integer)
Result = x + y
End Sub
その属性の目的は2つです:
マーシャリング
int a;
CallSomeMethodWithOutParameter(out a);
をし、コンパイラがa
はすでに電話をかける前の値を持っていることを確認する必要がないことを知っている:
言い換えれば、あなたはこれを行うことができます。 、属性なしで、次はC#で再び、必要とされるであろう一方
:
int a = 0; // <-- notice initialization here
CallSomeMethodWithOutParameter(ref a); // <-- and ref here
他の目的はを通じて例えば、異なる呼び出しコンテキストにマーシャリングされるメソッド呼び出しのためでありますP/Invoke、別のapp-domain、またはWebサービスに、マーシャリングルーチンにメソッドが返ってくるときに問題のパラメータに値が含まれることを通知するが、メソッドを呼び出すときにメソッドに値を渡す必要はない。
パラメータと戻り値をパッケージ化して、実際の呼び出しが行われるリモートの場所に転送する必要がある場合は、これが異なる場合があります。あなたはP /呼び出しを介して使用メソッド呼び出しにそれを指定した場合の方法はを返すときつまり
は、何のマーシャリングは、メソッドがと呼ばれている既存のパラメータ値の検査は行われません、されますが、その値はあなたの呼び出しコードに戻されます。この最適化は、マーシャリングルーチンが使用するかどうかに関係なく、実装の詳細であることに注意してください。この属性はルーチンにどのパラメータを指示するだけですか?これは、常に実行される命令ではありません。
私はVBについて知っているが、それはC#のout
キーワードと同等だと仮定しないでください:
それはちょうどref
のように振る舞うが、ためout
パラメータに渡された変数を初期化するために、発信者を必要としません。関数はそれを読み取ることはありません。
COMやその他のp-invokeを使用すると、マーシャリングに影響する可能性があります。
これは、パラメータがC#によって "out"パラメータとして見なされることを意味します。その場合には、C#コンパイラはそれを仮定します:
は他の言語では、さまざまな方法で[Out]
属性を使用することもできますが、そのような解釈は最も自然なものです。基本的には、パラメータは余分な戻り値に似ています。 (そこ微妙の程度が変化する過程の違い、たくさんのですが、それはoutパラメータの一般的な感です。)
ComVisible型では、生成されたCOMタイプライブラリが[out]属性でパラメータを修飾する必要があることを示すために使用されます。
メソッドのパラメータと戻り値に適用する場合、この属性はマーシャリング方向を制御するため、方向属性として知られています。 [OutAttribute]
は、CLRに、呼び出し時に呼び出し元から呼び出し元にマーシャリングするように指示します。呼び出し元と呼び出し先の両方は、アンマネージコードまたはマネージコードのいずれかになります。たとえば、P/Invoke呼び出しでは、マネージコードはアンマネージコードを呼び出しています。ただし、逆P/Invokeでは、アンマネージコードは、関数ポインタを介してマネージコードを呼び出すことができます。
[OutAttribute]
が無視される場合があります。たとえば、[OutAttribute]int
は意味をなさないので、[OutAttribute]
は単にCLRによって無視されます。文字列は不変なので、[OutAttribute]
stringも同様です。
したがって、この属性には意味がありません。この属性の詳細と<In()>
の属性はhereです。
問題のコードをコンパイルする場合にのみ、C#には関係ありませんか?コールサイトで "ref"と "out"が同じではないのですか?- 心配はありません:) –実際には、問題のルーチンを呼び出す前に変数が書き込まれていないと、コンパイラは静かに変数を保持する格納場所を初期化するコードを挿入しますそのようなコードがどこに置かれるかについての保証はなく、また、スコープを離れて再入力する変数が、再初期化なしに同じ記憶場所を使用し続けないという保証もありません。コンパイラは、呼び出されたルーチンが実際にそれを書き込むかどうかを確かめることができないため、変数が書き込まれたと見なすことはできません。 – supercat
@supercat:私たちは物事を検討しているレベルによって異なります。 「あなたのソースコードが有効であることを確認する」というレベル*は、変数が書き込まれたものとみなします。 「発光IL」レベルはありませんが、別のプラットフォームをターゲットとする別の実装では可能です*。 –