Home PC Games Linux Windows Database Network Programming Server Mobile  
           
  Home \ Programming \ C # compiler to achieve functional use in the runtime     - CentOS use wget (Linux)

- IP configuration under Linux (Linux)

- Java Generics (Programming)

- Django template inheritance child (Programming)

- Linux system network security tools sudo Introduction (Linux)

- Based Corosync + Pacemaker + DRBD + LNMP Web server to achieve high availability cluster (Server)

- MySQL5.6 based GTID master-slave replication (Database)

- AngularJS - Getting Started with Routing (Programming)

- Nginx supports user multi-threaded downloads and resume broken (Server)

- Servlet life cycle code examples (Programming)

- Detailed iptables (Linux)

- Github Remote Assistance (Linux)

- Getting the Linux shell expr use (Programming)

- Java multithreading easy to confuse the concept (Programming)

- To explore the Android ListView caching mechanism again (Programming)

- How MAT Android application memory leak analysis (Programming)

- NFS installation process under the CentOS (Linux)

- How to use Git to upload code to GitHub project (Linux)

- How to choose the first programming language based on the life you want (Programming)

- Linux System Getting Started Learning: In RedHat Linux driver compiled Ixgbe (Linux)

 
         
  C # compiler to achieve functional use in the runtime
     
  Add Date : 2018-11-21      
         
         
         
  Introduction

I want to share a new model, I developed to be used for compiling generic calculated using the run time in C #.

Over the past few years I have seen many examples in the programming and implement generic math in C #, but no one can do very well. In the first part I will be a step by step explanation of some of the examples I have seen, but also explain why they do not provide a good model to Functional.

I developed this model as part of my Seven Framework framework of the project. If you are interested, you can click on: https: //github.com/53V3N1X/SevenFramework.

Issues Overview

First, the fundamental problem is dealing with generic C #, just as in the base class. In addition System.Object base class, they have no implicit members. That is, with respect to the standard numeric types (int, double, decimal, etc.) they do not have arithmetic operators and implicit conversions. EXAMPLE 1 is an ideal situation, but in standard C # code is not compiled.

// EXAMPLE 1 ----------------------------------------
namespace ConsoleApplication
{Public class Program
    {Public static void Main (string [] args)
      {Sum < int> (new int [] {1, 2, 3, 4, 5});}
    public static T Sum < T> (T [] array)
    {T sum = 0; // (1) can not convert int to generic
        for (int i = 0; i < array.Length; i ++)
        sum + = array [i]; // (2) can not assume addition operator on generic
        return sum;}
              }
}

Indeed, EXAMPLE 1 will not compile because:

Type "T" does not ensure int values implicit conversion.

Type "T" can not ensure an add operation.

Now we understand the fundamental problem, let us begin to find some way to overcome it.

Interface-based solutions

C # where clause is a generic forced to meet some type of restraint. However, this method requires to have a C # does not exist in the basic numeric types. C # there is such a basic numeric types is the closest to force numeric types may become generic, but that does not help us on mathematics. EXAMPLE 2 still can not compile, but if we create our own basic numeric types, this will be possible.

Hide Copy Code

// EXAMPLE 2 ----------------------------------------
namespace ConsoleApplication {
public class Program
{
public static void Main (string [] args)
{
Sum < int> (new int [] {1, 2, 3, 4, 5});
}
public static T Sum < T> (T [] array)
where T: number // (1) there is no base "number" type in C #
{T sum = 0;
for (int i = 0; i < array.Length; i ++)
sum + = array [i];
return sum;}
}
}

Now EXAMPLE 2 will not compile because:

Without basic "value" type in C #.

If we realize our own basic "value" type, you can make it compile. We are required to do is to force the numeric types have C # basic numeric types and arithmetic operators generally implicit conversions. Logically speaking, this should be an interface.

However, even if we ourselves do numerical interface, we still have a major problem. We will not be able to type in C # do basic common mathematical calculations, because we can not change int, double, decimal and other source code to implement our interface. So, we not only have to write your own basic interface, but also need to write a wrapper for the primitive types in C #.
In Example 3, we have our own values Interface, "Digital", and int primitive type wrapper, Integer32.

// EXAMPLE 3 ----------------------------------------
namespace ConsoleApplication
{
public class Program
{
public static void Main (string [] args)
{
Sum (new Number []
{
new Integer32 (1), // (1) initialization nightmares ...
new Integer32 (2),
new Integer32 (3),
new Integer32 (4),
new Integer32 (5)
});
 }
public static Number Sum (Number [] array)
{
Number sum = array [0] .GetZero (); // (2) instance-based factory methods are terrible design
for (int i = 0; i < array.Length; i ++)
sum = sum.Add (array [i]);
return sum;
}
 }
public interface Number
{
Number GetZero (); // (2) again ... instance based factory methods are awful
Number Add (Number other);
}
public struct Integer32: Number // (3) C # primitives can not implement "Number"
{
int _value;
public Integer32 (int value)
{
this._value = value;
}
Number Number.GetZero ()
{
return new Integer32 (0);
} // (4) you will have to re-write these functions for every single type
Number Number.Add (Number other)
{
return new Integer32 (_value + ((Integer32) other) ._ value);
}
}
} // (5) this code is incredibly slow

Okay, so EXAMPLE 3 to compile, but it is a little worse, and why:

When programming interfaces used to initialize variables is very ugly.

You should not use a constructor or factory method as an instance method, because it is a bad design and a null reference exception is likely to result in the entire program.

You can not let the C # primitive types to achieve "Number" is possible only with a custom interface to the type of work.

It is not functional because you have to write every step to achieve a custom.

This code package because the basic type of work is extremely slow.

If you can not make complete functional library in C # generics math, no one will pay for this. Therefore, let us take over in the deal with this problem. If you can not modify the C # primitive data types to achieve the desired interface, then we create another type capable of handling all types of mathematical operations that have. This is a standard widely used in .Net framework provider model.

Side note / vent: Personally, I hate provider mode. But I still have not found an example of using delegates handled properly. When a large number of create a large number of providers who do not use a delegate.

When we use the provider model is still essentially doing the same thing as before, but a provider class will be able to handle all the math. Test it in EXAMPLE 4:

/ EXAMPLE 4 ----------------------------------------
namespace ConsoleApplication
{
public class Program
{
public static void Main (string [] args)
{
Sum < int> (new int [] {1, 2, 3, 4, 5}, new MathProvider_int ());
} // (1) all the methods need access to the provider
public static T
Sum < T> (T [] array, MathProvider < T> mathProvider)
{
T sum = mathProvider.GetZero ();
for (int i = 0; i < array.Length; i ++)
sum = mathProvider.Add (sum, array [i]);
return sum;}
    
public interface MathProvider < T>
{
T GetZero (); // (2) you still need instance factory methods
T Add (T left, T right);
}
 public class MathProvider_int: MathProvider < int>
{
public MathProvider_int () {}
int MathProvider < int> .GetZero ()
{
return 0;
} // (3) you still have to implement each function for every single type
int MathProvider < int> .Add (int left, int right)
{
return left + right;
}
}
} // (4) can be slow depending on implementation (this version is slow)

EXAMPLE 4 by moving all of the functional properties of the class to help, we can use C # basic types perform mathematical operations. However, this is only repair EXMAPLE 3 in the first question. We still need to address the following issues:

All methods must access mathProvider class. Although you can write code, do not have to let it pass between each function, this principle also applies to other similar structures.

You instantiate still based factory methods. In the above case, it is a conversion from int.

You still need to achieve functional properties for each simple type in the original code.

This is still quite slow, unless you do something for the provider "smart" caching. provider delivery and look really add a lot.

Now that we have tried to use interface value type itself (EXAMPLE 3) and an external provider (EXAMPLE 4) on. Using the interface we have not done more. What is certain is that we can use some clever clever storage method, but will eventually face the same problem: custom implementation must support at every step.

The final say ... in C # interfaces are not suitable for use in an efficient functional calculations.

Object Conversion

In C #, everything can be converted to System.Object type. So, I just put every thing into an object is then used to control the flow of the process it can be. Let's try.

Hide Shrink Copy Code

// EXAMPLE 5 ----------------------------------------
namespace ConsoleApplication
{
public class Program
{
public static void Main (string [] args)
{
MathProvider < int> .Sum (new int [] {1, 2, 3, 4, 5});
}
}
public static class MathProvider < T>
 {
public static T Sum (T [] array)
{// (1) still requires a custom implementation for every type
if (typeof (T) == typeof (int))
{
T sum = (T) (object) 0; // (2) largescale casting is very glitch prone
for (int i = 0; i < array.Length; i ++)
sum = (T) (object) ((int) (object) sum + ((int) (object) array [i]));
return sum;} t
hrow new System.Exception ( "UNSUPPORTED TYPE"); // (3) runtime errors
}}}
// (4) horribly slow ...

The fact is that it looks better than the interface method. The code is simple and easy to use. However, as before, we still have a lot of problems:

We still have to create a custom implementation for each type.

Meanwhile, we have a lot of type conversion may cause abnormal and very slow.

And do not support the types of runtime errors.

Poor performance.

Note: I do not know if they still do this in with F #, F #, but when I browse in the general standard math functions, they do look like the lowest level object conversion. Ridiculous!

Object into another dead end, but at least it is very simple to use.

proxy

Agent ...... really great!

We can not be like the original type as efficiently complete mathematical calculations. If there is no inheritance of each compiler can not make a judgment, and we can not let C # primitive types inherit our own class.

So, we put the general functionality of the code outside the class in general are removed it. We need to how to do it? proxy! As long as the general class set up a proxy, and dispensed from the outside at run time, these types can be recognized by the compiler.

However, we can delegate (proxy) into the generic class, and then assign an external compiler at run time commissioned (agent).

Hide Shrink Copy Code

// EXAMPLE 5 ----------------------------------------
namespace ConsoleApplication
{
public class Program
{
public static void Main (string [] args)
{// (1) requires a constructor method to be called prior to use
MathProviderConstructors.Construct ();
MathProvider < int> .Sum (new int [] {1, 2, 3, 4, 5});
 }}
public static class MathProviderConstructors
{
public static void Construct ()
{
// (2) still requires a custom implementation for every type
MathProvider < int> .Sum = (int [] array) =>
 {
int sum = 0;
for (int i = 0; i < array.Length; i ++)
sum = sum + array [i];
return sum;
};}}
public static class MathProvider < T>
{
// (3) still have runtime errors for non-implemented types (null-ref)
public static System.Func < T [], T> Sum;
}}
EXMAPLE 5 Functional is the best example. It runs fast, suitable for any type, and in addition to ensuring the static constructor must be called outside easy to use. However, it still has some flaws ... (1) constructor must be called, (2) for each type is still a need to implement a custom, (3) will throw a runtime error.

At this point we have to make some compromises. First, the run-time exception is almost inevitable. The only way I can think of is to make a custom plug-in is added to Visual Studio that will throw additional compilation errors. That for the purposes of this article, it is necessary to deal with the run-time exception. But the biggest problem is that we still have to write a function that we need to support each type. There must be a way to solve this problem!

Code

This is my current version of a generic mathematical model:

using Microsoft.CSharp; using System;
using System.CodeDom.Compiler;
using System.Reflection;
namespace RuntimeCodeCompiling {
public static class Program
{
public static Action action;
public static void Main (string [] args)
{
Console.WriteLine ( "Sum (double):" + Generic_Math < double> .Sum (new double [] {1, 2, 3, 4, 5}));
Console.WriteLine ( "Sum (int):" + Generic_Math < int> .Sum (new int [] {1, 2, 3, 4, 5}));
Console.WriteLine ( "Sum (decimal):" + Generic_Math < decimal> .Sum (new decimal [] {1, 2, 3, 4, 5}));
Console.ReadLine ();
}
#region Generic Math Library Example
public static class Generic_Math < T>
{
public static Func < T [], T> Sum = (T [] array) =>
{// This implementation will make this string be stored in memory during runtime,
// So it might be better to read it from a file
string code = "(System.Func < NUMBER [], NUMBER>) ((NUMBER [] array) =>
{NUMBER sum = 0; for (int i = 0; i < array.Length; i ++) sum + = array [i]; return sum;}) ";
// This requires that "T" has an implicit converter from int values and a "+" operator
code = code.Replace ( "NUMBER", typeof (T) .ToString ());
// This small of an example requires no namspaces or references
Generic_Math < T> .Sum = Generate.Object < Func < T [], T >> (new string [] {}, new string [] {}, code);
return Generic_Math < T> .Sum (array);
};
}
/// < Summary> Generates objects at runtime. < / Summary>
internal static class Generate
 {
/// < Summary> Generates a generic object at runtime. < / Summary>
/// < Typeparam name = "T"> The type of the generic object to create. < / Typeparam>
/// < Param name = "references"> The required assembly references. < / Param>
/// < Param name = "name_spaces"> The required namespaces. < / Param>
/// < Param name = "code"> The object to generate. < / Param>
/// < Returns> The generated object. < / Returns>
internal static T Object < T> (string [] references, string [] name_spaces, string code)
{
string full_code = string.Empty;
if (name_spaces! = null)
for (int i = 0; i < name_spaces.Length; i ++)
full_code + = "using" + name_spaces [i] + ";";
full_code + = "namespace Seven.Generated
{ ";
full_code + = "public class Generator
{ ";
full_code + = "public static object Generate ()
{Return "+ code +";}}} ";
CompilerParameters parameters = new CompilerParameters ();
foreach (string reference in references)
parameters.ReferencedAssemblies.Add (reference);
 parameters.GenerateInMemory = true;
CompilerResults results = new CSharpCodeProvider () CompileAssemblyFromSource (parameters, full_code).;
if (results.Errors.HasErrors)
{
string error = string.Empty;
foreach (CompilerError compiler_error in results.Errors)
error + = compiler_error.ErrorText.ToString () + "\ n";
throw new Exception (error);
}
MethodInfo generate = results.CompiledAssembly.GetType ( "Seven.Generated.Generator") GetMethod ( "Generate").;
return (T) generate.Invoke (null, null);
}
}
#endregion
}}

Code works:

If the general mathematical code is stored as a string, use the string hacking (aka macros aka string replace), to change the code at runtime. We can write a function and then change the type of the function when using this function. Therefore, we can assume that there must be a generic mathematical operators to implement this function.

The first time the function is called pan, it will build itself and re-assigned automatically. Thus, we do not have to deal with a stupid constructor, we only need to according to the desired functional structure.

As far as I know, you can not compile runtime compiler to use a single object, I just I need to compile a return value types. There may be an alternative, especially if you use a serialization technique of the time, but I am not very familiar with the deterioration degree format, so this method may be easier for me.
advantage:

Each type requires only a version of the code.

There is no set method or constructor call method as we hoped it would self-configuration.

fast! This method is far as I know the only delegate calls cost overhead.

Small drawback :( these "shortcomings" can be overcome)
1. It can be annoying to write generic mathematical function as a string. Solution: I propose to write generic code in a separate file and parse. Such strings are not permanently stored in memory, you can still edit it, like in Visual Studio using C # as standard.

2. This is not an example of cross-platform. Patch: It is easy to achieve cross-platform functionality. According to their website said that as a reflection and runtime library that contains compiled Mono project. So long as the dynamic compiler can make search run "Generate" functional class cross-platform.

3. If the generic "typeof (T) .ToString ()" is embedded in the generics, the code will now collapse. Patch: Create a function and then create an appropriate string representation of this type and source code to achieve the same goal using some kind.

4. We still have compilation errors. Tell us custom type "struct Fraction128" forget overloaded "+" operator. It will also throw a runtime error. Patch: This problem can write a VS plug-in at compile time to detect the type of functional operation used contains the basic values and operators to be repaired. I just point out to these questions tell you that it is fixable, I will not do that. To use the time, do not do stupid things,: P

in conclusion

By using the run-time compiler, you can exist mathematical operators and value type conversion assumptions identified for the establishment of mandatory, so you can do some real meaning of math students. It is fast, as opposed to other methods described in this article is easy to maintain, and very powerful.
     
         
         
         
  More:      
 
- Python Django model within the class meta Detailed (Programming)
- Linux System Getting Started Learning: Linux command in w (Linux)
- Linux network monitoring tools ntopng installation (Linux)
- MySQL related statements (CRUD) (SQLyog software) (Database)
- No password on Oracle and MySQL login (Database)
- PLSQL Developer synchronization table tools (Database)
- DRBD Principle and Features Overview (Server)
- Is Linux the most secure operating system (Linux)
- Forwarding module with Apache reverse proxy server (Server)
- Single Instance ASM under CRS-4124, CRS-4000 error handling (Database)
- Tomcat installation under Linux (Server)
- error 1819 (HY000): your password does not satisfy the current policy requirements (Database)
- iOS in the event delivery and the responder chain (Programming)
- How to use nmap command in Linux (Linux)
- Let MySQL 5.6 support Emoji expression (Database)
- Linux dynamic libraries and Guide (Programming)
- VirtualBox - Linux system virtual machine shared folders (Linux)
- Selection sort, insertion sort, and Shell sort (Programming)
- Linux system performance and usage activity monitoring tools -Sysstat (Linux)
- Google open source TCP team repaired the Linux kernel TCP flaw (Linux)
     
           
     
  CopyRight 2002-2022 newfreesoft.com, All Rights Reserved.