我希望将代码中某些基于反射的部分替换为使用动态运行时编译更好的部分。环顾四周,我看到Mono和Microsoft都有单独的编译器即服务解决方案:Mono.CSharp
和Microsoft.CSharp
。
由于存在提出基于意见的问题的风险,我想知道这两者是如何比较的?
据我所知,从一个非常肤浅的初步调查来看,它们通常都提供CAAS功能。我能够使用Microsoft.CSharp编译“Hello World”类并执行它。虽然我还没有对Mono做同样的事情,但我认为它可以做同样的事情。
有没有人对这两种情况都有任何经验,可以就此问题发表评论吗?
编辑:我不是在询问Mono的C#和微软的C#的比较 - 我们已经熟悉并使用它们。问题是关于两个 CAAS ( Compiler-as-a-Service )解决方案。
CAAS (但无论如何)不是.NET运行时的标准部分,即还没有System.Compile
命名空间。两个解决方案Mono.CSharp
和Microsoft.CSharp
是C#的单独非标准CAAS解决方案。他们的界面非常不同,因此存在问题。
答案 0 :(得分:4)
现在的Microsoft.CSharp(.net 4.5)是C#编译器用来为C#动态表达式发出绑定的API。因此它是C#编译器,但非常有限。 .NET和Mono都实现了相同的API(dll),因此您可以在.NET上编译并在Mono上运行,反之亦然。
Mono.CSharp是Mono C#编译器的评估者样式API。它允许您编译任何C#类文本代码(表达式,语句,类型声明等)并执行它。它严重依赖System.Reflection和System.Reflection.Emit。
这些都与CodeDom没有任何关系。
答案 1 :(得分:0)
我现在已经将Mono.CSharp
与Microsoft.CSharp
进行了比较,结果是Mono的版本在比较中表现不佳。
我用两个动态编译器编译了以下代码:
using System;
using CompilerServiceTest;
public class LalaDynamicImpl : ILala
{
private static int _counter;
public void DoLala()
{
_counter++;
}
}
主程序看起来像是:
public interface ILala
{
void DoLala();
}
public class LalaStaticImpl : ILala
{
private static int _counter;
public void DoLala()
{
_counter++;
}
}
public class Program
{
public static void Main(string[] args)
{
Message("Compiling dynamic lala...");
var lala = BuildDynamicLala();
Message("Testing dynamic lala...");
Test(lala);
Message("Sleeping for 1s...");
GC.Collect();
Thread.Sleep(1000);
Message("Testing static lala...");
Test(new LalaStaticImpl());
}
private static void Test(ILala lala)
{
var watch = Stopwatch.StartNew();
for (var i = 0; i < 1000000000; i++)
lala.DoLala();
Console.WriteLine(watch.Elapsed);
}
}
在我的机器上,结果是:
Microsoft.CSharp
编译的动态编译类: 1.9s Mono.CSharp
编译的动态编译类: 10s 结果与Mono团队提到here以及Marek Safar在他的答案中提到的内容相对应 - Microsoft.CSharp
编译器服务是实际编译器的包装器,代码在编译和优化与普通代码相同。 Mono.Csharp
编译器服务与Mono编译器是分开的,而且更像是一个“eval”机器。它没有像标准编译器那样优化代码。
基本上,似乎Mono编译器服务并非真正用于性能关键场景,而是用于丰富的功能,学习,测试等。
使用.NET 4.0(VS 2010)和Mono 3.2.3在Windows 7 64位计算机上测试。