Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9366

自分的ILノート

$
0
0

はじめに

これは私がILについて調べたことを忘れないようにメモする場所です。前提知識が確実に欠如しております。
間違いがございましたらご指摘お願いします。
特に明示しない場合は .NET Framework 4.8 を使い、規格はECMA-335に準ずるものとします。
どんどん更新していきます。(気分次第)

ジェネリクス

classC<T>{Tinst;}

T!0になる。よって上記のコードは

.class private auto ansi beforefieldinit C`1<T> extends [mscorlib]System.Object
{
    .field private !0 inst
    // .ctor 省略
}

簡単に書くと

.class private C`1<T>
{
    .field private !0 inst
}

C`1<T>C<T>でもOK。ただし、class C<T>class Cが両方あると.NET言語では片方しか参照できない。最初に書いた方が参照できる。

説明

ECMA-335 II.7.1 Typesでは、型定義のジェネリックパラメータは'!' Int32、メソッド定義のジェネリックパラメータは'!!' Int32となっている(Int32は0から数えたindex)。つまり、Class<T,U>.Method<V>()があったとすると、T!0U!1V!!0となる。

ちょいまてや

SharpLabで見てみるとldtoken !Tとかldtoken !!Vとかになってるじゃないですか! ldtoken !0ldtoken !!0じゃないの?

ilasm.exe をつかうか

ilasm.exe で以下のようなコードをコンパイルしてみた。

.assembly extern mscorlib {}
.assembly generics.exe {}

.class public Program
{
    .method static void Main() 
    {
        .entrypoint
        call class [mscorlib]System.Collections.Generic.List`1<!0> class C<int32>::GetList()
        call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
        call void [mscorlib]System.Console::WriteLine(object)
        ret
    }
}

.class public abstract sealed C`1<T>
{
    .method public static class [mscorlib]System.Collections.Generic.List`1<!T> GetList()
    {
        newobj instance void class [mscorlib]System.Collections.Generic.List`1<!T>::.ctor()
        ret       
    }
}

実行結果

System.Collections.Generic.List`1[System.Int32]

え、普通にいけるやん……。
ECMA-335ではこんな記法書いてなかったんだけどな……。

考察

  • T!Tなら、コンパイラ負荷は少なそう。
    • ソースコード→ILのコード→ILのバイナリーコード であればわざわざindex調べる必要がある!0!!0のような書き方より!T!!Tにした方がコンパイル速度も速そう。
  • IL(というかアセンブリ)は多様な書き方を許すべきであるはず。
    • わざわざTと名前がついているのにオペランドにTを用いてはいけません、とする理由はない。
  • !Tは型パラメータを指して、!0は入力された型を指すのでは?
    • call class [mscorlib]System.Collections.Generic.List`1<!T> class C<int32>::GetList()ができないのかその証拠。
    • !TListを返すのではなく、!0、つまりint32Listを返すのだから。
    • call命令の時点で型は決まっているから、抽象的な型パラメータを用いるのは間違っている。
    • ちなみに call class [mscorlib]System.Collections.Generic.List`1<int32> class C<int32>::GetList().method public static class [mscorlib]System.Collections.Generic.List`1<int32> GetList()を指すため不可。

Viewing all articles
Browse latest Browse all 9366

Latest Images

Trending Articles