Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vale.ini
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Microsoft.Accessibility = NO
Microsoft.Passive = NO
Microsoft.Suspended = NO
Microsoft.Vocab = NO
Microsoft.Spacing = NO
Microsoft.Semicolon = NO # Mostly just picks up code
Microsoft.SentenceLength = NO # Mostly just picks up code
Microsoft.Dashes = NO
Expand Down
4 changes: 4 additions & 0 deletions .vale/styles/FernStyles/Acronyms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ exceptions:
- XSS
- YAML
- ZIP
- SEO
- TLS
- BCL
- LLM
- MDX
- SEO
- AWS
Expand Down
4 changes: 4 additions & 0 deletions .vale/styles/FernStyles/Headings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ exceptions:
- Support
- Markdown
- Docs
- Mono
- Unity
- SDK
- SDKs
- API Reference
- API Explorer
- GitHub
Expand Down
227 changes: 227 additions & 0 deletions fern/products/sdks/overview/csharp/version-compatibility.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
---
title: .NET compatibility
description: Learn about supported .NET Framework versions (net462, net472, net48) and Unity compatibility for Fern-generated SDKs.
---

Fern-generated .NET SDKs support modern .NET versions, .NET Framework versions, and Unity.

Because these SDKs are built with modern C# features, you'll need the following even when targeting older .NET Framework targets:
- A modern compiler (Visual Studio 2022 or .NET SDK)
- The appropriate .NET Framework Developer Pack or reference assemblies

## Supported frameworks

Fern .NET SDKs support [all officially supported .NET versions](https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-framework), except for net35.

| Framework | Target Framework Moniker (TFM) |
|--------|----------|
| .NET 9 | net9.0 |
| .NET 8 | net8.0 |
| .NET Framework 4.8.1 | net481 |
| .NET Framework 4.8 | net48 |
| .NET Framework 4.7.2 | net472 |
| .NET Framework 4.7.1 | net471 |
| .NET Framework 4.7 | net47 |
| .NET Framework 4.6.2 | net462 |

<Note>
The C# language version is determined by your compiler, while the target framework determines which runtime and base class library APIs are available. Fern SDKs use modern C# features but compile to older framework versions.
</Note>

<AccordionGroup>
<Accordion title="IDE compatibility">
All major IDEs support Fern-generated SDKs when targeting `net462`, `net472`, and `net48` versions:

- **Visual Studio 2022** (recommended) - Works out of the box. Set `<LangVersion>` in your project and install the appropriate [developer pack](#developer-packs).
- **Visual Studio 2019** - Supports C# 9 natively. For newer C# versions, add the `Microsoft.Net.Compilers.Toolset` package.
- **Rider** - Uses Roslyn. Set `<LangVersion>` and ensure reference assemblies are available.
- **VS Code** - Works via OmniSharp and .NET SDK builds.
- **Unity** - Uses Unity's own C# compiler. See [Using SDKs with Unity](#using-sdks-with-unity).

<Info>
You can "bring your own compiler" with the `Microsoft.Net.Compilers.Toolset` package on any environment.
</Info>
</Accordion>
<Accordion title="Compiler compatibility">

Use the **Roslyn compiler** (`csc`) that comes with Visual Studio 2022+ or the .NET SDK. Set your C# version via `<LangVersion>` to `latest`, `preview`, or a specific version (minimum `9`).

Fern's .NET SDK doesn't support the legacy Mono compiler (`mcs`, `gmcs`) or the pre-Roslyn `csc.exe` compiler. Use Roslyn even when building on Mono.

<Info title="Building on Mono">

Use the .NET SDK (`dotnet`) with the `Microsoft.NETFramework.ReferenceAssemblies` package to supply `net48` references on non-Windows. Use Roslyn via `dotnet build` or Mono's MSBuild.

```bash title="macOS/Linux"
dotnet build -c Release
```
</Info>
</Accordion>
<Accordion title="Developer packs">

- [.NET Framework 4.6.2 Developer Pack](https://dotnet.microsoft.com/en-us/download/dotnet-framework/net462)
- [.NET Framework 4.7.2 Developer Pack](https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472)
- [.NET Framework 4.8 Developer Pack](https://dotnet.microsoft.com/en-us/download/dotnet-framework/net48)
</Accordion>
</AccordionGroup>

## Using SDKs with Unity

Unity controls its own C# compiler and .NET profile, which affects how you use Fern's .NET SDK.

<AccordionGroup>
<Accordion title="C# language version">
Unity compiles projects using Roslyn, typically supporting C# 9 (varies by Unity version). You can't force Unity to use a newer C# compiler by changing your package because Unity controls the compiler inside the Editor.
</Accordion>
<Accordion title="API compatibility level">
Configure this in Unity: `Edit → Project Settings → Player → Other Settings → Api Compatibility Level`

- **.NET Standard 2.1** (recommended for cross-platform plugins)
- **.NET Framework 4.x** (Unity's "4.x equivalent" profile)

</Accordion>
<Accordion title="Required assemblies">

Unity doesn't support NuGet packages, so you must manually download and add these assemblies to your Unity project:

| Assembly | NuGet Package |
|----------|---------------|
| Microsoft.Bcl.AsyncInterfaces | [10.0.0-preview.6.25358.103](https://www.nuget.org/packages/Microsoft.Bcl.AsyncInterfaces/10.0.0-preview.6.25358.103) |
| OneOf | [3.0.271](https://www.nuget.org/packages/OneOf/3.0.271) |
| OneOf.Extended | [3.0.271](https://www.nuget.org/packages/OneOf.Extended/3.0.271) |
| System.Buffers | [4.6.1](https://www.nuget.org/packages/System.Buffers/4.6.1) |
| System.IO.Pipelines | [10.0.0-preview.6.25358.103](https://www.nuget.org/packages/System.IO.Pipelines/10.0.0-preview.6.25358.103) |
| System.Memory | [4.6.3](https://www.nuget.org/packages/System.Memory/4.6.3) |
| System.Runtime.CompilerServices.Unsafe | [6.1.2](https://www.nuget.org/packages/System.Runtime.CompilerServices.Unsafe/6.1.2) |
| System.Text.Encodings.Web | [10.0.0-preview.6.25358.103](https://www.nuget.org/packages/System.Text.Encodings.Web/10.0.0-preview.6.25358.103) |
| System.Text.Json | [10.0.0-preview.6.25358.103](https://www.nuget.org/packages/System.Text.Json/10.0.0-preview.6.25358.103) |
| System.Threading.Tasks.Extensions | [4.6.3](https://www.nuget.org/packages/System.Threading.Tasks.Extensions/4.6.3) |
| portable.system.datetimeonly | [9.0.0](https://www.nuget.org/packages/portable.system.datetimeonly/9.0.0) |

</Accordion>
</AccordionGroup>

## Project configuration examples

Use SDK-style projects where possible, as they provide modern compilers and simpler multi-targeting. If you have a classic project format, consider converting to SDK-style. The [legacy projects section](#legacy-projects) covers legacy setups that can't be converted.

<Note title="Building on macOS/Linux">
When building for `net48` on macOS/Linux, you won't have the Windows targeting packs. Add the reference assemblies package:

```xml title="YourProject.csproj"
<ItemGroup>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
</ItemGroup>
```
This provides the `net48` reference assemblies so Roslyn can compile for `net48` on any platform. You'll still need Mono or Wine to execute the result.
</Note>

<AccordionGroup>
<Accordion title="SDK-style projects (recommended)">

Targeting `net48` with modern C#

<Steps>
<Step title="Configure your project">

<Info title="Prerequisite (Windows)">
Install the [.NET Framework 4.8 Developer Pack](#developer-packs) so the `net48` reference assemblies are available to the compiler.
</Info>

```xml title="YourProject.csproj"
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Target .NET Framework 4.8 -->
<TargetFramework>net48</TargetFramework>

<!-- Use a modern C# version -->
<LangVersion>latest</LangVersion>

<!-- Optional, but recommended for better warnings -->
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
```
</Step>

<Step title="Build your project">
```bash
dotnet build -c Release
```
</Step>

<Step title="Multi-target (optional)">
To support multiple frameworks, use `<TargetFrameworks>`:
{/* <!-- vale off --> */}
```xml title="YourProject.csproj"
<TargetFrameworks>net48;net8.0</TargetFrameworks>
```
{/* <!-- vale on --> */}
</Step>
</Steps>
</Accordion>
<Accordion title="Legacy projects">

For older MSBuild/Visual Studio versions, Visual Studio 2019, or legacy `packages.config` setups, add a modern Roslyn toolset and target the old framework.

<Steps>
<Step title="Install target packs">
Install the appropriate [.NET Framework Developer Pack](#developer-packs) so Visual Studio can find the reference assemblies.
</Step>

<Step title="Set language version">
```xml title="YourProject.csproj"
<PropertyGroup>
<!-- Unlock modern C# -->
<LangVersion>latest</LangVersion>
</PropertyGroup>
```
Or use a specific version: `9`, `10`, `11`, `12`, or `preview`.
</Step>
<Step title="Add modern compiler">

```xml title="YourProject.csproj"
<ItemGroup>
<PackageReference Include="Microsoft.Net.Compilers.Toolset" Version="x.y.z">
<!-- Keep it private: -->
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
```
This ensures your build uses a modern `csc.exe` even if your IDE/MSBuild is older.

</Step>
</Steps>
</Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
<Accordion title="Type or namespace IsExternalInit not found">
Add a small shim in your project or reference a helper package.
</Accordion>
<Accordion title="Reference assemblies for .NETFramework,Version=v4.8 were not found">
- Windows: install the [.NET Framework 4.8 Developer Pack](#developer-packs).
- Cross-platform/CI: add `Microsoft.NETFramework.ReferenceAssemblies` to the project (as `PrivateAssets=all`).
</Accordion>
<Accordion title="VS 2019 can't parse newer syntax">
Add `Microsoft.Net.Compilers.Toolset` to the project, or move to VS 2022+.
</Accordion>
<Accordion title="CS0619: Constructors of types with required members are not supported">
This error occurs when using the `required` keyword with older Visual Studio versions. Follow the instructions at [Legacy projects](#legacy-projects) to add a modern compiler.

<Note>
Some versions of Visual Studio may show this error in the IDE but compile the project successfully when using the package-provided compiler.
</Note>
</Accordion>
</AccordionGroup>









2 changes: 2 additions & 0 deletions fern/products/sdks/sdks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ navigation:
- page: Publishing to NuGet
path: ./overview/csharp/publishing-to-nuget.mdx
slug: publishing
- page: Version compatibility
path: ./overview/csharp/version-compatibility.mdx
- page: Adding custom code
hidden: true
path: ./overview/csharp/custom-code.mdx
Expand Down