In my actual projects I like to use a combination of C# and F# to implement the needed applications. I think C# is a very efficient programming language to implement the user interface and the business layer and F# may be used in the low level layers of the application e.g. the data layer or the execution layer. Especially if you have data which is stored in trees or tree like structures, the god F# support for recursion will make it a perfect language to deal with such data structures. Therefore, I want to show you within this article, how you can use your C# data classes in F# functions.
The Demo Solution
Within the demo application I want to analyse data which is stored in a tree structure. The main application is a C# console application. Also the data classes are written in C#. But the analysis of the data should be implemented by using recursive function calls. Therefore the data analysis should be implemented by using F#.
I have created a solution with three assemblies:
– DemoApplication: written in C#, contains the console application
– DataAnalysis: written in F#, contains the data analysis functions
– DataDomain: written in C#, contains all data classes
The DemoApplication assembly will use the DataAnalysis assembly as a service provider. Both assemblies will use the data classes of the DataDomain assembly.
The data domain should contain a data class with a tree structure. Within the demo application a tree of data class objects should be created. The demo application should analyse the data and find the maximum depth for each data object. For example if a data object is used inside the tree structure in the second and forth layer, the maximum depth of this data class is “4”.
Data Domain
The data domain assembly contains the data class Element. Each element may have a list of sub elements to create a tree structure. Furthermore the member MaxDepth is available to store the maximum depth for this data object within the tree structure. The following source code shows the according C# class.
public class Element { public Element() { } public List<Element> ChildElements { get; set; } public int MaxDepth { get; set; } }
Console Application
Within the console application the functionality of this little demo solution should be shown. A tree structure will be created which contains six elements.
Element A is the root element. The other elements are used in a tree like structure. Element F is a sub element of three other elements and it is used in different layers or different depths of the tree. The following picture shows the dependencies between the different elements.
The comsole application is used to create the document tree. Afterwards the function calculateMaxDepth of the DataAnalysis assembly is used to calculate the depth of each element. The following source code shows the console application.
static void Main(string[] args) { //prepare elements Element a = new Element(); Element b = new Element(); Element c = new Element(); Element d = new Element(); Element e = new Element(); Element f = new Element(); a.ChildElements = new List<Element>() { b, d, f }; b.ChildElements = new List<Element>() { c }; d.ChildElements = new List<Element>() { e, f }; e.ChildElements = new List<Element>() { f }; List<Element> rootElements = new List<Element>() { a }; //calculate LayerSearch.calculateMaxDepth(rootElements); //show results Console.WriteLine("a: " + a.MaxDepth.ToString()); Console.WriteLine("b: " + b.MaxDepth.ToString()); Console.WriteLine("c: " + c.MaxDepth.ToString()); Console.WriteLine("d: " + d.MaxDepth.ToString()); Console.WriteLine("e: " + e.MaxDepth.ToString()); Console.WriteLine("f: " + f.MaxDepth.ToString()); Console.ReadKey(); }
Data Analysis
The data analysis is written in F#. Within a recursive function call the element tree will be analysed. The F# function uses the C# class to get the elements and to update the MaxDepth property. To use the C# data class and the according assembly, an open command must be added (line 4). Afterwards the Element class can be used (line 15) and it is possible to update the properties if the data class (line 9).
module UseCSharpClassInFSharp.LayerSearch open System.Collections.Generic; open UseCSharpClassInFSharp; let rec private calculateMaxDepthInternal (element : Element) layer = if element <> null then if element.MaxDepth < layer then element.MaxDepth <- layer if element.ChildElements <> null then for child in element.ChildElements do calculateMaxDepthInternal child (layer+1) let calculateMaxDepth rootElements : List<Element> = for element in rootElements do calculateMaxDepthInternal element 1 rootElements
Summary
It is very easy to call functions provided by F# assemblies in C# code. And it is also easy to use C# classes in F# code. This will allow you to implement a solution by mixing different programming languages. So you can use the language specific advantages during the implementation of the different parts of you application.