理由はC#のコンパイラの発光callvirt指導のためには、GetType()メソッドを電話のかけ方は?
-
21-08-2019 - |
質問
私は好奇心を知るのはなぜこのことが起こっているのです。をお読みくださいコード例としては、下記に対応するILした放出されるコメントを下記の各部署:
using System;
class Program
{
static void Main()
{
Object o = new Object();
o.GetType();
// L_0001: newobj instance void [mscorlib]System.Object::.ctor()
// L_0006: stloc.0
// L_0007: ldloc.0
// L_0008: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
new Object().GetType();
// L_000e: newobj instance void [mscorlib]System.Object::.ctor()
// L_0013: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
}
}
なぜ、コンパイラを発するの callvirt
の一部が call
のでしょうか。があることにより、コンパイラのう発 callvirt
指導のための非仮想メソッド?いる場合のコンパイラを放つ、 callvirt
非仮想メソッドはこの問題をタイプ。
解決
リーダーシップ安全です。
技術的にはC#のコンパイラな 常に 使用 callvirt
のためのstaticメソッド&方法上で定義された値型を用い call
.多くは経由してご提供いただいた callvirt
IL。
の違いを振りの投票をい call
は、"オブジェクトとしても使われ、コール"はnullになります。 callvirt
一方でチェックのためのnullでない場合、戻るNullReferenceException必要があります。
- のためのstaticメソッドは、オブジェクトの型オブジェクトではnullになります。数理計算上の差異の処理のための値です。そのため
call
使用しています。 - のその他の言語でデザイナーが決定したものと
callvirt
では、JITコンパイラを確認する対象のオブジェクトを使うと、通話がnullではないでも非仮想インスタンス法の..彼らは価値の安全性。
参照:Jeff側には良い仕事ではそのデザイン種類"の章の"にCLR C#第2版
他のヒント
これを参照してください。エリックGunnersonによっての古いブログ記事ます。
ここでは、ポストのテキストはいます:
のなぜC#は常にcallvirtを使用していますか?の
この質問は、内部のC#の別名に思い付いた、と私は答えは、一般的な興味があるだろうと思いました。それは答えが正しいと仮定しています - それはかなりしばらくしている。
。.NET IL言語はcallvirtが仮想関数を呼び出すために使用されると、コールとcallvirt命令の両方を提供します。あなたはC#が生成するコードに目を通す場合でも、あなたはそれも関係なし仮想関数が存在しない場合には「callvirt」を生成していることがわかります。それはなぜそれをするのでしょうか?
私は私が持っている言語設計上の注意を通じて戻った、と彼らは我々が1999年12月13日にcallvirtを使用することを決めたことを非常に明確に述べます。残念ながら、彼らはそれを行うための私たちの理論的根拠をキャプチャしていないので、私は私の記憶から行かなければならないつもりです。
私たちは、誰かからレポート得ていたNULLポインタのメソッドを呼び出したコードを書いていた(C#を使用して.NETグループのありそうなものを(それはまだその時点)で、C#の名前が付けられていないと思った)、彼らはdidnのこの方法は、(すなわち、 『これは』ヌルだったが、この方法では何もそれを使用しない)任意のフィールドにアクセスしなかったため、」tが例外を取得します。その方法は、この点を使用した、例外をスローした他の方法、およびヘッド傷続いたのビットと呼ばれます。彼らはそれを考え出した後、彼らはそれについての私達にメモを送信します。
私たちは、nullのインスタンスでメソッドを呼び出すことができるということは少し奇妙だと思いました。ピーターGoldeはPERF影響が常にcallvirtを使用してので、我々が変更を行うことを決めたことを十分に小さいものであったかを確認するためにいくつかのテストをしました。
GetType()
ではないという点で、(perhaps-)余談面白いと... virtual
は珍しいです/ 194484 /いただきまし--奇妙なコーナーケース・ホード・見・イン・C-またはネット194671 /#194671" >非常に、非常に奇妙なものがします。
タグ(実際の質問にややオフトピックであるようウィキとしてマークされました)
コンパイラは最初の式でo
の実数型を知らないが、それは第二の発現の本当のタイプを知っているん。それは一度に一つの文を見ているように見えます。
これは、罰金です。これは、両方の呼び出しは、インスタンスが実行時に呼び出すになるとこのような単純な場合には非常に可能性があります。
私はcallvirt
がこれまでに非仮想メソッドのために放出されると信じていませんが、メソッドをオーバーライドすることはないだろうので、それがあったとしても、それは(明白な理由のために)問題はないでしょう。
私は、潜在的に(我々はそれがない見ることができるにもかかわらず)GetType
をオーバーライドしていたかもしれない別のタイプのdowncastedインスタンスを含むことができ、変数への最初の割り当てからだという推測をハザードでしょう。第二は、Object
以外に何もすることができませんでした。