We have a solution containing C# and F# code. In this post, I’ll show you how the CompilationRepresentationAttribute
helps to use F# code from C# by preventing naming conflicts on types and modules.
In our F# code, we have a module that “extends” the type Task
with some useful functions:
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Task =
open System.Threading.Tasks
let Ignore (t : Task<_>) =
task {
let! _ = t
()
}
let map (f : 'a -> 'b) (t : Task<'a>) =
task {
let! a = t
return f a
}
let fromOption (taskOption : Task<_> option) =
task {
match taskOption with
| Some t ->
let! value = t
return Some value
| None -> return None
}
The task
computation expression is from the library Ply.
The module uses the CompilationRepresentation
attribute with the argument CompilationRepresentationFlags.ModuleSuffix
so that the module is seen by C# as TaskModule
, and not as Task
, which would be the default.
F# allows having types and modules with shared names – even with multiple modules. C# does not.
Using the attribute eliminates the conflict between our Task
module and the type Task
from the System
namespace. Without the attribute, we would always have to fully qualify at least one of them, when we need both in a class.
That’s all for today! Happy coding.
F# code can still use the module with e.g. Task.Ignore
.

This blog post is made possible with the support of Time Rocket, the product this journey is all about. Take a look (German only).
Find all blog posts about our journey to F# here.