Use dotnet 11 RC sdk

Godot Version

v4.7.2.stable.mono.arch_linux [ed1daf0bf]

Question

Hello, I’m still new to Godot, learning how it works via GDScript but I see myself switching to C# at some point. (I have a background in C#/dotnet)

What I wonder is if it would be possible to use newer version of dotnet? Or how exactly does Godot integrate with dotnet? Can I easily bring my own SDK version?

I’m most interested in using dotnet 11 RC because of the new language feature in C#.
Explore union types in C# | Microsoft Learn and Explore closed hierarchies in C# | Microsoft Learn are a very interesting addition to the latest C#. So I wonder if I can easily use that, or if it a world of pain to avoid.

What are your experiences?

As far as I know, godot currently uses dotnet 8, so even if you use a higher version, it’ll simply use an older version of dotnet as they should mostly be backwards compatible.

So you can use dotnet sdk 11 but target net8.0 and it all might work out?

I have Dotnet 10 installed but the project targets dotnet 8, yes.

But if there are big changes in dotnet 11 it might not work.

I was also hoping to try this out and start exploring the .NET 11 RC with Godot. I tried both in 4.7.2 and 4.8.0-dev.6. If I compile my project and try and debug with net10.0 targetFramework it works fine, but as soon as I switch to net11.0 I get a FileNotFoundException:

System.IO.FileNotFoundException: Could not load file or assembly ‘System.Runtime, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’. The system cannot find the file specified.File name: ‘System.Runtime, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’at System.ModuleHandle.ResolveType(QCallModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)at System.ModuleHandle.ResolveTypeHandle(Int32 typeToken, RuntimeTypeHandle typeInstantiationContext, RuntimeTypeHandle methodInstantiationContext)at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type genericTypeArguments, Type genericMethodArguments)at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(MetadataToken caCtorToken, MetadataImport& scope, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder1& derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctorWithParameters, Boolean& isVarArg)    at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes)at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType)at Godot.Bridge.ScriptManagerBridge.LookupScriptsInAssembly(Assembly assembly) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs:line 319
at GodotPlugins.Main.LoadProjectAssembly(Char* nAssemblyPath, godot_string* outLoadedAssemblyPath) in /root/godot/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs:line 154

I tried pinning the .NET version in global.json, but that didn’t help either. The project builds without issue, just fails at runtime.

I imagine this means that Godot needs to support .NET 11 in some form before this will work? Is this generally tracked by the Godot team or do we need to open a specific issue/proposal about it?

Yes, Godot specifically needs to support a specific dotnet version. The currently targeted version is dotnet 8. You do not need to open a ticket about it, the team is not focused on constantly updating to the latest version of dotnet since the LTS one still works and is supported.

Answering my own question, in case it helps the next person.

You can use the .NET 11 RC SDK with Godot 4.7 without changing the target framework. Godot ships and runs on .NET 8, so I kept <TargetFramework>net8.0</TargetFramework> and only switched the language version:

<LangVersion>preview</LangVersion>
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>

The SDK builds it and the editor loads it fine, since the assembly still targets the runtime Godot has.

The one catch is C# 15 union types. The compiler accepts union syntax, but it looks for two types that only exist in the .NET 11 base library, so on net8.0 you get “Predefined type System.Runtime.CompilerServices.IUnion is not defined”. Declaring them yourself is enough; the compiler only needs the shape:

namespace System.Runtime.CompilerServices
{
    public interface IUnion
    {
        object? Value { get; }
    }

    [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)]
    public sealed class UnionAttribute : Attribute { }
}

One file in the project, and union Marker(Running, Upcoming); compiles and runs inside Godot. Delete it the day the target framework moves to net11.

Rider needed the EAP build to understand the syntax; the release build flagged union pattern matches as errors while dotnet build was green. With the EAP it is all quiet, and being able to use Rider to its full extent again was most of the point.