簡體   English   中英

是否可以將 C# 編譯為 IL 並將生成的 IL 反編譯為 F#?

[英]Is it possible to compile C# into IL and decompile the resulting IL into F#?

C# 編譯成 IL,然后使用 ILSpy 或 dotPeek 很容易反編譯回 C#。

是否有任何工具可以將相同的 IL 反編譯為 F#?

即,是否有通過 IL 將 C# 轉換為 F# 的偷偷摸摸的方法?

理由:

  • 我們有一個非常大的 C# 項目,想要“實現功能性”。
  • 翻譯是一項艱巨的工作。
  • 如果第一遍的翻譯可以自動化,我們可以在之后手動改進它

即這會比在 F# 中從頭開始編寫所有內容更快。

我們在 F# 方面還沒有經驗,因此這個問題可能很幼稚。

進一步說明 是的,我們在 C# 中使用函數式的東西,但出於各種原因,我們希望在 F# 中實現完整的功能。 此處不討論該選擇,但感謝您對此的評論。

慣用的 F# 代碼使用不同的類型、方法和結構。 將 C# 生成的 IL“反編譯”到 F# 並沒有什么好處,尤其是當您考慮到可以很容易地與 C# 代碼交互時。 更糟糕的是,反編譯任何東西都會讓你丟失大量信息——本地名稱、常量、注釋等等。 這並非不可能,但是您正在浪費大量精力來重建一些中間步驟。

將 C# 代碼分解成可以慢慢替換為 F# 代碼的部分。 這樣,您就有機會生成良好的 F# 代碼,並根據需要逐步替換所有內容。 不要從頭開始編寫任何東西 - 盡可能多地保留舊代碼,並且只更改需要更改的內容以改進與 F# 代碼的接口。

C# 已經是一種“功能強大”的語言 - 不像 F# 那樣簡潔和富有表現力,但是您可以在 F# 中以相當簡單的方式在 C# 中完成的事情很少,而在 C# 中則無法完成。 這意味着逐漸轉變為函數式風格並不像聽起來那么困難——而且這是你無法避免的工作,如果你的目標是(出於某種原因;我希望你也有一個實際的目標,這是只是一個中間步驟:) 功能代碼。

正如此處所回響的,當您編譯為 IL 時,您會丟失寶貴的信息。 閱讀 C# 代碼來翻譯所有高級信息更可行。

剛剛破解了一個SyntaxWalker

  public class FsVisitor : CSharpSyntaxWalker
        {
            public override void VisitUsingDirective(UsingDirectiveSyntax node)
            {
                PrintLn("open {0}", node.Name);
            }

            public override void VisitClassDeclaration(ClassDeclarationSyntax node)
            {
                PrintLn("type {0} =", node.Identifier);
                Enter();
                base.VisitClassDeclaration(node);
                Exit();
            }

            public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
            {
                var isStatic = node.Modifiers.Any(t => t.ValueText == "static");
                var modifiers = String.Join(" ", node.Modifiers);

                PrintLn("{0}{1} ({2}) = ",
                    isStatic ? $"{modifiers} member " : $"member {modifiers} this.",
                    node.Identifier,
                    String.Join(", ", node.ParameterList.Parameters.Select(p => $"{p.Identifier} : {p.Type}")));
                Enter();
                base.VisitMethodDeclaration(node);
                Exit();
            }

            public override void VisitInvocationExpression(InvocationExpressionSyntax node)
            {
                PrintLn("{0}", node);
                base.VisitInvocationExpression(node);
            }

            private StringBuilder builder = new StringBuilder();
            private int intendLevel = 0;

            void Enter() => intendLevel++;
            void Exit() => intendLevel--;

            void Print(string format, params object[] args)
            {
                if (format == null) return;
                builder.Append('\t', intendLevel);
                builder.AppendFormat(format, args);
            }

            void PrintLn(string format = default, params object[] args)
            {
                Print(format, args);
                builder.AppendLine();
            }

            public override string ToString() => builder.ToString();
        }

我用一個簡單的 C# 程序試了一下:

        var code =
        @"    
        using System;

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

            private void SayHello()
            {
                Console.WriteLine(""Hello"");
            }
        }";

    var visitor = new FsVisitor();
    visitor.Visit(CSharpSyntaxTree.ParseText(code).GetCompilationUnitRoot());
    Console.WriteLine(visitor.ToString());

輸出:

open System
type Program =
        static member Main (args : string[]) =
                Console.WriteLine("Hello World")
                Console.ReadKey()
        member private this.SayHello () =
                Console.WriteLine("Hello")

當然,輸出是針對一個簡單的程序。 支持合理的轉換需要做更多的工作,但也許轉換不一定是完美的。 也許如果它為您提供了支架,您可能可以用慣用的 F# 來填充它。

一如既往的自動化:

在此處輸入圖片說明

我只是一個業余愛好者,所以我不保證以下內容完全准確......首先,我將假設您當前的 C# 基礎是用慣用的 C# 編寫的,因此您當前的 C# 項目遵循面向對象的范例。 如果這是准確的,並且您希望“功能齊全”,那么您唯一真正的選擇是按照功能范式重新編寫您的項目。 如果存在這樣的 IL 轉換器,則轉換后的程序將以面向對象的方式將您的 C# 編譯為 F#(F# 是一種功能優先的語言,但也可以用作面向對象的語言)。 此外,正如其他人所指出的,您可以從 F# 調用您的 C# 代碼,但這不會將您的 C# 項目轉換為以功能方式運行。 您仍然必須按照設計使用的方式使用 C# 項目 - 通過 F# 以面向對象的方式使用。 您可能可以在 F# 中圍繞 C# 程序編寫某種形式的包裝器,使其以功能方式運行,但如果您的 C# 項目基於對象層次結構,那么這可能不是太簡單,您可能會發現您沒有最終得到一個功能齊全的包裝器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM