◆ .NET Framework も .NET Core も対応
◆ インストールなしで使える zip 形式のリリース
◆ C# や F# から作った dll (exe) を C# のコードで見れる

これの続きです
exe や dll の中の情報がみたいというものです
C++ などネイティブのものと .NET のものは拡張子が一緒でも中身は別でそれぞれ別のツールが必要でした

.NET で作ったものは Visual Studio についてる ildasm や JETBRAINS の dotPeek を使って見ることができました
ildasm は Visual Studio に付属なので .NET Core には付いておらず対応もしていません
dotPeek はインストール必要ですがどっちも見れました

今回 ILSpy というツールを見つけました
インストール不要の zip でダウンロードできる Windows アプリです

.NET Framework だけでなく .NET Core で作った dll にも対応です
.NET Core で作られた exe は実体はなく起動するだけみたいで何も表示できませんでしたが dll ファイルの方を開くと表示できました

C#

この C# コードを build して開いてみます
「dotnet new console」 コマンドで作ったデフォルトのままです

using System;

namespace example
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}

ilspy

namespace, class, method とツリーになっていて メソッド内ではコードが復元できています

// example.Program
using System;

private static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}

IL から復元なので private や public など省略したものがついていたり 完全に元のコードになるわけではないですが ほぼ完全なものが多く普通に読めます

F#

F# って書き方が C# と比べると結構違うのでどうなってるのか気になります
下のコードで試してみました
これも「dotnet new console --language f#」コマンドで作ったままです

open System

[<EntryPoint>]
let main argv =
printfn "Hello World from F#!"
0 // return an integer exit code

結果は

ilspy-fs

大きく違っています
References に FSharp.Core と System.Runtme.Extensions が入っています
namespace には <StartupCode$example> から始まるのが 3 種類できています
example のところは fsproj ファイルの名前です

今回のコードでは <StartupCode$example> 系には特にプログラムはないようです
代わりに C# のときには何もなかった 「-」 という namespace に Program クラスがあります
これがエントリーポイントになるクラスでした

// Program
using Microsoft.FSharp.Core;
using System.IO;

[CompilationMapping(SourceConstructFlags.Module)]
public static class Program
{
[EntryPoint]
public static int main(string[] argv)
{
ExtraTopLevelOperators.PrintFormatLine(new PrintfFormat<Unit, TextWriter, Unit, Unit, Unit>("Hello World from F#!"));
return 0;
}
}

printfn は FSharpCore の中にある ExtraTopLevelOperators.PrintFormatLine という関数になっていました


F# だとエントリーポイント関数を書かないこともできるので こういうコードも試してみました

open System

printfn "Hello World from F#!"

すると 「-」 namespace の Program に main メソッドはなくなりました

// Program
using Microsoft.FSharp.Core;

[CompilationMapping(SourceConstructFlags.Module)]
public static class Program
{
}

代わりに <StartupCode$example>.$Program の main@ メソッドにありました

// <StartupCode$example>.$Program
using Microsoft.FSharp.Core;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;

internal static class $Program
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
internal static int init@;

public static void main@()
{
ExtraTopLevelOperators.PrintFormatLine(new PrintfFormat<Unit, TextWriter, Unit, Unit, Unit>("Hello World from F#!"));
}
}

こうやって C# と F# を比べて見るのもおもしろいですね