How does LINQPad compile code? - c#

I am guessing it neither invokes csc.exe or implement an entire compiler, so how does it work?
Update: Thanks to Jon Skeet for the pointer to code that was easy to learn from.
string c = #"
public class A
{
public static void Main(string[] args)
{
System.Console.WriteLine(""hello world"");
}
}
";
CodeDomProvider compiler = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.WarningLevel = 4;
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
CompilerResults r = compiler.CompileAssemblyFromSource(parameters, c);
Assembly a = r.CompiledAssembly;
Type[] ts = a.GetTypes();
Type t = ts[0];
object o = t.GetMethod("Main").Invoke(null, new object[] { new string[] { } });

From "How LINQPad Works":
LINQPad compiles your queries using .NET's CSharpCodeProvider (or VBCodeProvider)
Obviously there's rather more to it, but that's the bit you asked about - read the link for more details.
If you want to have a look at a rather more simplistic implementation, you could download the source code for Snippy, the little tool I created for C# in Depth. Again, it uses CSharpCodeProvider - and it's a simple enough example that it's easy to understand, with any luck. (There are only a few classes involved, IIRC.)

Jon's answer from almost 5 years ago is now out of date.
From "How LINQPad Works" (as at 29 Jan 2016):
LINQPad 5 compiles your queries using the Microsoft Roslyn libraries
(in the past it used .NET's CSharpCodeProvider and VBCodeProvider).
You can see an example of how to use Roslyn to compile your code here:
Learn Roslyn Now - Part 16 - The Emit API

Related

C# Reflection performance comparison when invoking class with parameter

I have heard a lot about Linq Expression performance. But wasn't able to check it myself.
Please take a look on the next .NET Core app example:
class Program
{
static void Main(string[] args)
{
var classType = Type.GetType("ConsoleApp1.TestClass");
var classConstructor = classType.GetConstructor(new[] { typeof(string) });
//var param = Expression.Parameter(typeof(string));
//var newExpression = Expression.New(classConstructor, param);
//LambdaExpression lambda = Expression.Lambda(newExpression, param);
//var compiled = lambda.Compile();
//var instance = compiled.DynamicInvoke("test");
//var instance = Activator.CreateInstance(classType, "test");
//var instance = classConstructor.Invoke(new object[] { "test" });
Console.ReadLine();
}
}
class TestClass
{
public TestClass(string param)
{
}
}
When I am running this code with Expression version uncommented then code works 10 times slower.
Please advice what could be wrong or it is as expected.
A simple benchmark shows interesting results. Durations are in milliseconds.
I just wanted to share the results I got. Seems like DynamicInvoke really has a big overhead (as #ivan-stoev pointed out)
I will add the results for both the .Invoke solution with a strongly typed lambda and the Roslyn compiled concrete class implementing a simple interface for instantiation.
ConstructorInfo is cached, and so is the compiled lambda expression.
For 10 million iterations each: (100 million instantiations for each method)
---------------------------------------------------------------------------
Benchmark Results:
---------------------------------------------------------------------------
Activator Constructor Compiled Lambda
---------------------------------------------------------------------------
Totals : 8121.2488 3067.6226 9353.8141
Average: 0.00081212488 0.00030676226 0.00093538141
Maximum: 922.5987 450.7662 1046.3734
Minimum: 0 0 0
---------------------------------------------------------------------------

Performance impact of using var type [duplicate]

This question already has answers here:
Will using 'var' affect performance?
(12 answers)
Closed 3 years ago.
I have noted in c# that using var improves your performance, especially when declaring variables of a specific class. I have done multiple bench marks and have got the same result every time. I have also read similar questions on this site and others. but no one has actually commented on this.
Can anyone please confirm or refute this.
I have a
class for image data, clsImageData
and collection clsImageDataCollection.
a function in collection class is SetCaseLowerCase().
Code is
private void SetCaseLowerCase()
{
foreach (var item in this)
{
item.DestinationImageName = item.DestinationImageName.ToLower();
}
}
Now if I use clsImageData instead of var, it performs slower, I have checked it with 100000 iterations. but results is always the same. also with other examples too.
Thanks
Edited
I have tested this simple code and got 7/10 times better performance using var. Please tell me what am I doing wrong, I am using VS 2017, debug mode for any CPU, my processor is quad core. Thanks
sw.Start();
for (int i = 0; i < 10000000; i++)
{
var xyz = "test";
}
StopClock(sw, "Example var - ");
sw.Start();
for(int i = 0; i<10000000; i++)
{
string xyx2 = "test";
}
StopClock(sw, "Example type - ");
var is compiled in a way, that makes the use of it equals to just declaring the variable/ type (except in cases it cant be done somehow else but using var ex: anonymous types). that means there are no performance changes at all. read more about var at https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var
here is a demonstration, type the following code:
var list = new List<int>();
note that when you hover above list your IDE says:
(local variable) List<int> list
the reason for that is that var is converted to the declared type, meaning that var is actually cosmetic and its use can not impact any performance.

Creating a Guid -> conversion from VB to C#

I have the following code in VB.Net and I'm trying to convert it to C#.
listContacts = ACT_FRAMEWORK.Contacts.GetContactsByID(Nothing, New Guid() {New Guid(ContactID)})
Below is my attempt so far:
Guid[] test = new Guid[1];
test[0] = Guid.NewGuid(ContactID);
contactList = actApp.Contacts.GetContactsByID(null, test);
The abover errors because NewGuid() takes no arguments. I have also tried.
test[0] = contactID1;
However, you can't convert from string to Guid. Can anyone help with this?
Guid.NewGuid is a method, and you're not calling that method from your VB code - you're calling the constructor accepting a string. You can call that same constructor in C#:
// Using an array initializer for simplicity
Guid[] test = { new Guid(ContactID) };
Or if you want to make the call in one line as per your VB code:
contactList = actApp.Contacts.GetContactsByID(null, new[] { new Guid(ContactID) });
I think it's a shame that NewGuid has that name rather than CreateGuid, but such is life :(
Using Guid.Parse will work too of course - judging by the .NET Core source code they behave extremely similarly; the constructor just handles overflow exceptions slightly differently.
Try Guid.Parse(ContactID.ToString());
if ContactID is actually a string , simple write Guid.Parse(ContactID);

Roslyn Scripting

Hi I want to use Roslyn to scripting in my app. But I have new (September) version and I am confused. I want to execute file with some simply function.
For example:
public int m(){
return 6;
}
I found some articles about it for example acticle. There is some way to do it, but in my version isn't Session.Create()
I want to use it like IronPython scripting
Something like:
var scriptEngine = new SciptEngine.ExecuteFile(fileWithFunction);
dynamic d = getFunction(m);
or
dynamic d = callFunction(m);
Is it possible or I must use IronPython scripting?
The API hasn't changed significantly since the original CTP that the article was written in. For your scenario:
var scriptEngine = new ScriptEngine();
var session = scriptEngine.CreateSession();
session.AddReference("System");
session.AddReference("System.Core");
session.Execute(#"public int m() { return 6; }");
int six = session.Execute<int>("m()");

Compile a C# Array at runtime and use it in code?

I know C# code can be compiled at runtime using C#. However I'm very very shaky at it since I just read about it a few minutes ago. I learn a lot better by examples. So tell me. If I want to compile something like:
// MapScript.CS
String[] LevelMap = {
"WWWWWWWWWWWWWWWWWWW",
"WGGGGGGGGGGGGGGGGGW",
"WGGGGGGGGGGGGGGGGGW",
"WWWWWWWWWWWWWWWWWWW" };
and use this array in my code, how would I go about it?
In pseudocode I want to do something like this:
Open("MapScript.CS");
String[] levelMap = CompileArray("levelMap");
// use the array
LINQ Expression trees are probably the friendliest way of doing this: Perhaps something like:
http://msdn.microsoft.com/en-us/library/system.linq.expressions.newarrayexpression.aspx
http://msdn.microsoft.com/en-us/library/bb357903.aspx
You can also generate the IL using OpCodes (OpCodes.Newarr). Easy if you are comfortable with stack-based programming (otherwise, can be challenging).
Lastly, you can use the CodeDom (which your pseudocode resembles), but--while the most powerful tool--it is less ideal for quick dynamic methods. It requires file system permissions and manual reference resolution since you are working closely with the compiler.
Sample from MSDN
var ca1 = new CodeArrayCreateExpression("System.Int32", 10);
var cv1 = new CodeVariableDeclarationStatement("System.Int32[]", "x", ca1);
Source - Creating Arrays with the Code DOM
If you want a straight up raw compile of a string, you can omit the object-oriented treatment of the statements and instead just build a big string. Something like:
var csc = new CSharpCodeProvider( new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } } );
var cp = new CompilerParameters() {
GenerateExecutable = false,
OutputAssembly = outputAssemblyName,
GenerateInMemory = true
};
cp.ReferencedAssemblies.Add( "mscorlib.dll" );
cp.ReferencedAssemblies.Add( "System.dll" );
cp.ReferencedAssemblies.Add( "System.Core.dll" );
StringBuilder sb = new StringBuilder();
// The string can contain any valid c# code, but remember to resolve your references
sb.Append( "namespace Foo{" );
sb.Append( "using System;" );
sb.Append( "public static class MyClass{");
// your specific scenario
sb.Append( #"public static readonly string[] LevelMap = {
""WWWWWWWWWWWWWWWWWWW"",
""WGGGGGGGGGGGGGGGGGW"",
""WGGGGGGGGGGGGGGGGGW"",
""WWWWWWWWWWWWWWWWWWW"" };" );
sb.Append( "}}" );
// "results" will usually contain very detailed error messages
var results = csc.CompileAssemblyFromSource( cp, sb.ToString() );
It appears that you are wanting to compile C# code in order to load a list of strings in a text (C#) file into a string array variable.
You don't need a c# compiler to load a list of strings from a text file into an array in memory. Just put one string per line in your text file, and read the file line by line in your code, adding each line to a List<String>. When you're done, list.ToArray() will produce your array of strings.
You can create a class CompiledLevel that inherits from ILevel which proposes a static property Level of type String[].
Then, before compiling, create a fake CompiledLevel.cs file built from a template of class filled with content of LevelMap (wwwggg...) (sort of concatenation).
One compiled, call Level property on the compiled class.
Create a service/factory/whatever to make it fancy :)

Categories

Resources