Some notes/feedback about C# target

I was not able to join latest Haxe event, but watched the replay videos afterwards and its cool to see updates from the Haxe team. Thanks a lot for that :pray:

During that event, Haxe’s C# target was mentioned as not being a first class citizen, kind of being under-maintained, and that it might eventually be replaced by some DLL assembly export at some point, like what was done for java target being replaced with jvm target.

I’d like to give some feedback regarding the usage I had of C# target, and also some thoughts about its relevance in the future of Haxe and some direct consequences it would have if code exported as plain C# was not a thing anymore.

C# is pretty popular nowadays thanks to Unity being used a lot. Unity is not only used for games, but also more and more as an alternative to Flash for interactive apps in general. Other popular tools like Godot are also embedding C# for scripting (and we can find haxe C# externs for it). That’s the most popular usages I know but there are certainly more to it.

Here’s some concrete feedback about my use of C# target with Unity:

I did use Haxe’s C# target to create a Unity backend for ceramic engine, which made it possible to make a 2D game entirely written in Haxe run inside Unity. Despite the quirks of C# target I had to workaround, I got fairly good performances by using the right Unity APIs (CommandBuffer) and “patching” some C# output (cs/internal/Runtime.cs) to prevent some implicit boxing of primitive values. Even managed to run ceramic editor (written in haxe) run inside Unity.

When using Haxe’s C# target with Unity, I export C# files and let Unity Editor do the compilation itself. I did not prebuild an assembly DLL file from Haxe because it was much more straightforward to let Unity do that : no need to manually link with Unity/.NET assembly files manually. As long as your haxe code has proper externs to Unity API & used plugins, C# files can be exported and then Unity will do the heavy build/link work. Another good addition is that, because C# output is exported as “one file per type/class”, Unity will be faster to reload additional builds as only a few files may have changed since last export.

If C# target was replaced with a DLL-assembly-only export, some issues would arise :

  1. Unity is very slow to reload a whole assembly DLL file. That would mean every new compilation would freeze unity a lot. Much more than when I’m exporting multiple C# files. Yes, “pre-built” DLL doesn’t mean faster import for Unity.
  2. Directly generating the assembly DLL would mean (I believe, tell me if I’m wrong) we can’t just use externs referencing other external C# API. We would have to link with other assemblies having that API. That would make the build process much more complicated compared to just dropping C# files into Unity.

So is retiring C# target really an option?

I understand that the original author of C# (and Java) targets is not really around anymore as mentioned by @Simn and it makes it difficult to maintain that target without proper resources, and apparently that target has issues other targets don’t have. I really acknowledge that.

That said, I wanted to share how much exporting C# code from Haxe is still useful, and I believe very relevant in the foreseeable future.

Despite all its current flaws, I hope C# target won’t go away anytime soon, even if it’s not the most efficient generated code, (even if optional args are generating garbage etc…), we can do awesome stuff with it, developers did build things with it and it would be pretty bad news if all that stopped to be possible in some future version of Haxe.

That seemed important for me to share this feedback.

I would also be glad to help in any way I can to keep this target alive or make it better (should I start learning OCaml? Only half-joking, if that could really help eventually, never too late to learn new things)

I am wondering what are the thought of the Haxe team regarding this, as well as the Haxe developers using/wanting to use this target. What do you think about the relevance of Haxe C# target nowadays and in the future (despite the current issues), and what would be the consequences of moving from C# code export to some prebuilt assembly DLL file export?

Anyway, thanks for reading this long and boring feedback :pray:and thanks to the Haxe team for making Haxe as good as it is now :pray::pray:


The issue is broader than the C# target, if you want to use haxe in something that doesn’t support it and comes with its own building step, a source target is pretty much the only solution.

So that also bring the question should the java target be removed in favor of the jvm target?

But for the C# target as a user of it I also don’t wish to see it removed, though the code for it is a bit convoluted (it shares thing with the java target) and a bit old.

I wonder if it’d be worth it to make a new C# target that targets newer .net runtime and C# version, reusing part of the old target where it makes sense.


Sounds like a good option, if there is actually the manpower to do that. I might really start taking a closer look at OCaml and haxe compiler in 2021 heh.

1 Like

Another potential use for it will be in the upcoming game S&Box, which is pretty much the same as Unity in terms of C# Scripting.

I might really start taking a closer look at OCaml and haxe compiler in 2021 heh.

I would also love to work on these targets… If only Haxe in Haxe would happen already so contributing would be a lot easier.

I was wondering if one of the ikvm’s would be useful, the concept seems to be around processing the jvm to a vm within cil.
I am not really sure on license implications, perhaps it’s too problematic. The original author seems to have moved away so it’s unclear which is the most relevant repo… license seem to differ between GPL’s. Perhaps it provides enough clues for the jvm target to also target CIL.

Just agreeing with @jeremyfa here:

We’ve used the C# and Javascript targets for some business applications - that’s right Haxe isn’t just for games, please tell everyone!

It has been a great combination. For example, an existing MVC based web app needs a page that is higher performance so we build a simple server endpoint in C# and a larger front end in Javascript. Sharing code across both targets to get the data types/etc lined up at compile time is a great feature and having the C# code output makes for an easy project to include and debug against. A dll version would probably work in this case too, but having the raw C# source available makes finding and fixing quirks much easier (just edit the source, see if that fixes things, and then port the fix back into Haxe).

I would say the C# output is not very pretty, but I think it was made to have maximum performance based on how it builds lookup tables/etc at compile time - maybe a Haxe insider can speak to that. I did a few performance tests (years ago now, maybe I can find the code) where I built a simple data model and a REST web api in pure C# and another in Haxe->C#. The Haxe->C# was about 20% faster than the pure C# version! This was mostly due to the JSON stringify being faster in Haxe compared to Newtonsoft JSON I used, but the ‘anonymous’ type object data in Haxe was also very fast. Writing the code in Haxe was also more efficient and flexible resulting in fewer lines of code and easier understanding of the project (anonymous functions, typedefs, etc).

So in general, please keep the C# target around in some form. With Net5+ I am seeing more uses and more platforms being available. I’m not a huge fan of C#, but it is well supported and probably always will be.

Is there a thread/discussion about the major hurdles to keeping the C# target going at this point? Is it falling behind on new Haxe features and just requires some maintenance, or are there major problems with the current system that are total show-stoppers?

On a final note, hopefully some progress can be made related to C# output in this issue: Array<T> variance on static targets · Issue #4872 · HaxeFoundation/haxe · GitHub
C# unserialized arrays are somewhat broken, however it looks like the problem is wider than just the C# target.