7

詳細を説明すると、C# の値型はコンパイラ/CLR によって非常に特別に扱われます。ただし、CLR 内部の型はさらに特別に扱われます。これが私が意味することです:

int a = 5;
int b = 10;
int с = a + b;
a.CompareTo(b);

Visual Studio でマウスをホバーするとint、実際にSystem.Int32構造体であることがわかります。それで大丈夫です。これで、ILDasm を取得して内容を調べることができます。これはSystem.Int32、タイプのフィールドが 1 つある非常に単純な構造体でありint32(これはint32CLR の内部にあります)、加算用のオーバーロードされた演算子がないことがわかります。

それで、これはどのようにint с = a + b機能しますか?再び ILDasm をつかみ、IL を調べます。System.Int32IL コードには がないことが判明しました。コンパイラは、それを に置き換える必要があることを自動的に理解しint32ます。そして、スタック上のaddカップルで機能するIL命令があります。int32さらに面白いことに、CLR ではSystem.Int32onのインスタンス メソッドを呼び出すことができますint32。私には黒魔術のように見えます。

ここで、純粋な理論的な質問に進みます。これSystem.Int32は他の型と同じように見えますが、C# で何らかの方法で作成できますか? 可能であれば、それを使って何か役に立つことはありますか (実際のint32フィールドは非公開です)。

編集:わかりました、もう少し明確にするために:この質問はintへのエイリアスであることについて何もありませんSystem.Int32。提供された例を使用して、例の後の最初の段落を置き換えintSystem.Int32スキップすることができます。本当の問題はvaluetype [mscorlib]System.Int32 a、単にint32 a.

4

3 に答える 3

2

したがって、次のコードを検討してください。

    static void Main(string[] args)
    {
        int x = 5;
        Print(x);
        Console.ReadLine();
    }

    static void Print(object x)
    {
        int y = (int)x;
        Console.WriteLine(y);
    }

ILDasm で:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  .maxstack  1
  .locals init ([0] int32 x)
  IL_0000:  nop
  IL_0001:  ldc.i4.5
  IL_0002:  stloc.0
  IL_0003:  ldloc.0
  IL_0004:  box        [mscorlib]System.Int32
  IL_0009:  call       void Test.Program::Print(object)
  IL_000e:  nop
  IL_000f:  call       string [mscorlib]System.Console::ReadLine()
  IL_0014:  pop
  IL_0015:  ret
} // end of method Program::Main

.method private hidebysig static void  Print(object x) cil managed
{
  .maxstack  1
  .locals init ([0] int32 y)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  unbox.any  [mscorlib]System.Int32
  IL_0007:  stloc.0
  IL_0008:  ldloc.0
  IL_0009:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_000e:  nop
  IL_000f:  ret
} // end of method Program::Print

[mscorlib]System.Int32ボックス化/ボックス化解除のみに使用されます。変数がスタックにあるときは、常にint32です。


Int32 および intから:

System.Int32 を int32 のシャドウ タイプと考えるとわかりやすいかもしれません。

次の C# コード:

int x = 0;
x.ToString();

これはILにありますか:

ldc.i4.0
stloc.0
ldloca.s 0
call instance class System.String [mscorlib]System.Int32::ToString()
pop

一見互換性のない System.Int32 構造体に int32 が渡されていることに注目してください。エンジンは、System.Int32 を int32 のシャドウ タイプとして認識するようにハードワイヤードされているため、この原因を許容します。

于 2012-10-26T08:45:52.303 に答える
1

int32int(== System.Int32)

.NETプリミティブ型の理解から:

int32 は CLR プリミティブです。次に、FCL では System.Int32 構造体で表されます。System.Int32 の整数値はその m_value フィールドに保持され、多くの整数関連のメソッドが System.Int32 で定義されています。

C# では、int は System.Int32 の単なるエイリアスであり、C# コンパイラでサポートされています。したがって、int と System.Int32 の間に依存関係はありません。

IL 「The Language of CLR」より:

.NET の下のすべてのコンパイラは、アプリケーションの開発に使用される言語に関係なく、中間言語を生成します。実際、CLR は、アプリケーションの開発に使用される言語を認識しません。すべての言語コンパイラは、中間言語と呼ばれる統一された共通言語を生成します。

したがって、C#System.Int32には IL がありint32ます。私は、C# コードから直接 IL を操作する方法を知りません。また、実際にその理由がわかりません。

1つあります:C#/ VB.NetでインラインILを許可するツール


intvsについてSystem.Int32

SO に関する int および System.Int32 に関する投稿: C#、int、または Int32? 気にする必要がありますか?

MSDN:

  1. Int32 構造体
  2. int (C# リファレンス)

それはすべて同じです:

Int32 i = new Int32();
Int32 j = 5;
int x1 = 2;
Int32 x2 = x1;

intいわばシンタックスシュガーです...実際にはSystem.Int32です

また、C# 言語仕様 4.1.4 単純型を参照してください。

C# には、単純型と呼ばれる定義済みの構造体型のセットが用意されています。単純な型は予約語で識別されますが、これらの予約語は、表で説明されているように、System 名前空間の事前定義された構造体型の単なるエイリアスです。

どこ

  1. 短い => System.Int16
  2. int => System.Int32
  3. 長い => System.Int64

等々。

于 2012-10-26T07:07:38.710 に答える
0

CLR には、CorElementType 列挙型によって定義される一連のプリミティブ型があります。 http://msdn.microsoft.com/en-us/library/ms232600.aspx

add、sub、div、rem などのオペコードは、これらの型で動作します。JIT はこれらを高速なアセンブリ コードに変換します。新しいものを定義することはできません。興味があれば、SOS を使用して生成されるコードを見ることができます。

言語エクスペリエンスをエミュレートする場合は、型で演算子のオーバーロードを使用できます。 http://msdn.microsoft.com/en-us/library/8edha89s.aspx

于 2012-10-26T06:58:26.797 に答える