I want to convert the C# classes in my console app to F#, one at a time. With stunning help from Co-pilot, I got one class done. But I can’t build with it. So I made a tiny test solution, to investigate. I’m using .NET 7.0 SDK (v7.0.201)
The C# compiler complains:
I’m just learning how to write a class in F#, and I can’t see how to fix this.
#!/bin/bash
dotnet new sln
dotnet new console -o Console
dotnet new classlib -o LibraryC
dotnet new classlib -lang "F#" -o LibraryF
dotnet sln add Console/Console.csproj
dotnet sln add LibraryC/LibraryC.csproj
dotnet sln add LibraryF/LibraryF.fsproj
dotnet add LibraryF reference LibraryC
dotnet add Console reference LibraryF
cat << 'EOT' > LibraryC/Class1.cs
namespace LibraryC;
public class Class1 {
public virtual int Number => 17;
public virtual string Greeting() => "Hello";
}
EOT
cat << 'EOT' > LibraryF/Library.fs
namespace LibraryF
open LibraryC
module Class2 = // ANSWER: Remove this.
type Class2() =
inherit Class1()
member this.Junk() = "not static"
override this.Number = 42
override this.Greeting() =
let fromBase = base.Greeting()
$"{fromBase} from Class2 {this.Number}"
EOT
cat << 'EOT' > Console/Program.cs
using LibraryC;
using LibraryF;
var class1 = new Class1();
Console.WriteLine($"{class1.Greeting()} {class1.Number}");
var class2 = new Class2();
Console.WriteLine($"{class2.Greeting()} {class2.Number}");
EOT
I wrote the above script by hand. This way of exporting a solution seems very useful, so I opened an issue for a dotnet command to export a .sln file as a sequence of dotnet commands.
As mentioned in the comments, you are declaring a module Class2
inside LibraryF
and only inside this module, you have a class Class2
. F# modules are compiled as static classes and so if you open LibraryF
, the Class2
refers to the static class representing the module.
You can resolve this by dropping the module declaration from the F# library (you would only need a module if you also wanted to have top-level let bindings such as functions or global values, but if you do not need those, you can put the class directly inside a namespace):
namespace LibraryF
open LibraryC
type Class2() =
inherit Class1()
member this.Junk() = "not static"
override this.Number = 42
override this.Greeting() =
let fromBase = base.Greeting()
$"{fromBase} from Class2 {this.Number}"