G#: a Kotlin and Swift flavoured language that compiles to the CLR
GSharp Programming Language
At a glance
- What is it?
- G# is an experimental .NET language that takes null safety and data classes from Kotlin, value semantics from Swift, and Go and Python flavoured syntax, and compiles to ordinary .NET assemblies you can call from C#. Its tooling is unusually complete for a language at version 0.5, with an MSBuild SDK, a language server, a REPL and a C# migration tool.
- Who is it for?
- G# suits a .NET developer who wants null safety and data classes without leaving the runtime, and the fact that G# assemblies are ordinary .NET assemblies means the adoption risk is mostly about the language itself rather than about the platform. It does not suit you if you need a stable toolchain, since the version numbers are still in the 0.5 range and the release history shows a very recent 0.5.26 build.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three languages borrowed from, one runtime kept
G# is described as a modern, simple and accessible programming language for.NET, with Kotlin and Swift style semantics and Go and Python inspired syntax, on the CLR you already know.
The borrowing is specific rather than a general impression. Kotlin and Swift supply the semantic model: null safety as a distinct type rather than a nullable annotation, data classes with structural equality and copy semantics, and top-level statements as the entry point. Go supplies the concurrency model, with channels, a go keyword and scope blocks. Python supplies the brace and indentation feel of the surface syntax.
The README's own example shows all of it at once:
package hello
import System
data class Point(X int32, Y int32)
func describe(p Point?) string {
if let q = p {
return "point at (${q.X}, ${q.Y})"
}
return "nowhere"
}
let origin = Point(0, 0)
let moved = origin with { X = 3 }
Console.WriteLine(describe(moved)) // point at (3, 0)
Console.WriteLine(moved == Point(3, 0)) // True — structural equality
Console.WriteLine(describe(nil)) // nowhereThe type is written after the name, Point is a data class so two points with the same coordinates compare equal, the with expression produces a modified copy, the nil is a valid value of the optional type Point?, and the if let binds the unwrapped value. The string interpolation uses a dollar sign, which is the Swift spelling rather than the C# one.
One line in the README is worth pausing on, because it tells you how the project treats its own examples: every sample in the README compiles and runs with the current compiler. For a language this young, that is a stronger claim than it sounds, and it is the reason to trust the feature list over a design document.
The version numbering gives the context. The releases are v0.5.6 and v0.5.7 on the same day in October 2026, then v0.5.26 three days later, with the last push on 2026-10-22. A language in its 0.5 series that is still cutting releases that frequently is pre-1.0 in the strict sense.
Null safety as a type, and data classes that carry their weight
The two features the documentation leads with are null safety and data modelling, and they are the reason a .NET developer would look at G# at all.
Null safety by design means T? is a distinct type, and if let, guard let, while let, the null-conditional operator and the null-coalescing operator all make the absent case explicit, with the compiler refusing to let you forget it. On the CLR that is a significant difference from C#, where a reference type is nullable by default and the compiler will not stop you. The cost is that every call site that touches a possibly absent value has to say what it does about it, and the language pays that cost in verbosity rather than in annotations.
Data modelling that pulls its weight means data class and data struct give you structural equality, with-copy and deconstruction from a single line. The example above shows two of the three: moved == Point(3, 0) is True because the equality is structural, and origin with { X = 3 } is the copy. Deconstruction is the third, and it is the one that turns a data class into something pleasant to work with in a pattern match, where the same declaration that gives you equality also gives you the ability to take the pieces apart.
The rest of the feature list is about the surrounding ecosystem rather than the language core. The whole .NET ecosystem means every BCL type, every NuGet package, LINQ, P/Invoke and events are callable directly with no bindings or wrappers, and the G# assemblies are ordinary .NET assemblies consumable from C# and F#. That last point is the one that matters for adoption, because it means G# is not a walled garden and a mixed codebase is a normal outcome rather than a project boundary.
The syntax position is stated as small and predictable: type-after-name declarations, no semicolons, no ceremony, and top-level statements as the entry point, so a one-file program is a real program.
On the interop side, the example shows CLR generics using the bracket spelling, List[int32], lambdas flowing into LINQ, and DllImport functions binding as P/Invoke stubs, with events, delegates, ref and out parameters, function pointers and struct marshalling covered in a separate interop reference.
Channels and scope blocks, and what scope actually guarantees
Structured concurrency is the third headline feature, and it is the most Go-shaped thing in the language.
The example is a producer and a consumer:
package pipeline
import System
func produce(ch out chan[int32]) int32 {
for var n = 1; n <= 3; n = n + 1 {
ch <- n * 10
}
return 0
}
let ch = chan[int32](3)
scope {
go produce(ch)
for var i = 0; i < 3; i = i + 1 {
Console.WriteLine("got ${<-ch}")
}
}
Console.WriteLine("pipeline drained")The chan type is declared with an element type and a capacity, the out parameter modifier on the producer marks the channel as an output parameter, the go keyword starts a task, and the scope block wraps the whole interaction.
What scope guarantees is the important part. It guarantees the goroutines it spawns finish, and surface their failures, before the block exits. The documentation is explicit that the child work is joined and failures are observed before control leaves the scope, and that the block prints the drained message only after the loop has consumed all three values.
That is a stronger guarantee than a bare task spawn, and it is the reason to prefer scope over a plain go. The failure observation is the part that matters in practice, because a task that fails silently inside a scope is a bug the compiler helps you avoid and a task that fails silently outside one is the kind of thing that costs a day of debugging.
The concurrency guide covers the patterns the language does not show in the README, including select-style patterns, buffered channels and close semantics, and the example above uses a buffered channel of capacity 3, which is why the producer can write three values without the consumer having to read first.
The for loop syntax is worth noting too, because it is not C-style. It is for var n = 1; n <= 3; n = n + 1, with the declaration in the header, which is the Kotlin form rather than the C form, and it works for the channel read as well.
Tooling, and the migration tool that doubles as a conformance gate
The tooling is the part of this project that is most unusual, and it is the part that suggests the author intends G# to be a real language rather than a toy.
The MSBuild SDK is called Gsharp.NET.Sdk, and it makes dotnet build, run, test and pack work for .gsproj projects, including Roslyn source generator hosting and code analyzers. The templates package is Gsharp.Templates with console, library, xUnit and web templates. Gsharp.Repl gives you gsi, an interactive REPL and .gs file runner, installed as a global dotnet tool. Gsharp.Gsfmt provides gsfmt, described as the option-free canonical G# formatter used by editors, CI, the SDK and the migration tool. And Gsharp.Cs2Gs provides cs2gs, which migrates C# projects to G#.
The cs2gs tool is where the engineering effort went, and the description is worth reading carefully. It doubles as the compiler's quality gate: every C# syntax construct is classified in a machine-checked coverage inventory, a per-construct conformance corpus is translated, compiled, IL-verified and byte-compared against its C# baseline on every pull request, and newly discovered gaps are automatically filed as issues.
That is a serious approach to a compatibility claim. Comparing IL rather than text means the check catches semantic differences that a textual diff would miss, and doing it per construct rather than per program means a failure points at a specific language feature. The automatic issue filing closes the loop, so a gap found by the tool becomes work rather than a note in a document.
Editor support is complete for a language at this stage. The VS Code extension is gsharplang.vscode-gsharp, giving syntax highlighting, completion, hover, diagnostics, formatting, build and run commands and debugging. The Visual Studio 2022 and 2026 extension adds native projects, NuGet, managed debugging, Test Explorer, templates and six G# themes on top of the same language server.
The repository layout backs the claim that this is a full project rather than a compiler prototype. There is src/ for the implementation, test/ and e2etests/ for the suites, a test-assets/ directory, samples/ with .gs files and matching .golden files, bench/ for benchmarks, build/, design/ for design history, docs/, website/ for the documentation source, tools/cs2gs/, and a version.json.
Getting started, and the project file that is really a .NET project
The setup path is the standard dotnet one, with a twist in the SDK name.
You need the .NET 10 SDK, and then:
dotnet new install Gsharp.Templates
dotnet new gsharp-console -n MyApp
cd MyApp && dotnet runThe interesting detail is that a .gsproj file is a regular SDK-style .NET project that happens to compile .gs files:
<Project Sdk="Gsharp.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>MyApp</RootNamespace>
</PropertyGroup>
</Project>So the G# project is a .NET project with a different SDK identifier. That is the whole integration story in five lines, and it is why dotnet build, run, test and pack work without any special tooling. The TargetFramework is net10.0, which ties the language to the current .NET release.
Templates for libraries, xUnit test projects and web apps ship in the same package, under the names gsharp-lib, gsharp-xunit and gsharp-web, so a project starts from a template rather than from an empty file.
The documentation is a full site rather than a single page, hosting the language tour, tutorials, the language guide, the specification and the tooling reference, with the source in the website/ directory. There is a Tour of G# that walks through pattern matching, interfaces, extension functions, error handling and generics, and a design/ directory in the repository that records design history.
The repository also carries the usual institutional files, a CLAUDE.md for coding agents, a SECURITY.md, a CONTRIBUTING.md, a global.json pinning the SDK, a Directory.Build.props and Directory.Build.targets for the shared build configuration, a nuget.config, and a GSharp.slnx solution file in the newer XML format. The licence is MIT, and the NuGet package Gsharp.NET.Sdk is published with the rest.
Editorial conclusion
G# suits a .NET developer who wants null safety and data classes without leaving the runtime, and the fact that G# assemblies are ordinary .NET assemblies means the adoption risk is mostly about the language itself rather than about the platform. It does not suit you if you need a stable toolchain, since the version numbers are still in the 0.5 range and the release history shows a very recent 0.5.26 build. Before you evaluate it, try the REPL and the templates first rather than a from-scratch project, and read the language specification in the documentation, because a language that mixes three other languages' idioms needs a written spec more than most.
Frequently asked questions
What is G# and what does it borrow from other languages?
It is a .NET language with Kotlin and Swift style semantics and Go and Python inspired syntax. It takes null safety, data classes and top-level statements from Kotlin and Swift, and channels, go and scope blocks from Go, while compiling to ordinary .NET assemblies.
How do I start a G# project?
Install the .NET 10 SDK, run dotnet new install Gsharp.Templates, then dotnet new gsharp-console -n MyApp, and cd MyApp and dotnet run. A .gsproj is a regular SDK-style .NET project with the Gsharp.NET.Sdk SDK identifier.
What does the scope block guarantee in G#?
It guarantees that the goroutines it spawns finish, and surface their failures, before the block exits, so child work is joined and failures observed before control leaves the scope. The concurrency guide also covers select-style patterns, buffered channels and close semantics.
Is G# stable enough to use?
The releases are still in the 0.5 series, with v0.5.26 published on 2026-10-18, and the project is MIT licensed and actively pushed. The README states that every sample in it compiles and runs with the current compiler, but the version numbering indicates a pre-1.0 language.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/davidobando-gsharp)