79

EDIT [Nov 29 2020]: .NET 5.0 is out now, but the solution below is still required if you're targetting .NET Standard 2.1


C# 9.0 is still under development. There are a couple references which lead me to believe it should be testable now (some of it, anyway).

  1. A Microsoft blog by Mr. Awesome himself, introducing the features. https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/
  2. The language tracking page on github: https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md

I'm using VS 2019 16.7 Preview 3.1. I've selected the language version as Preview for a project.

Some C# 9 features, I can use. Like: Dictionary<string, object> Stuff = new()

But using the new init feature gives me this error: Error CS0518 Predefined type 'System.Runtime.CompilerServices.IsExternalInit' is not defined or imported

How do I fix this?

Examples of code causing the error:

class Test
{
   public int Hello { get; init; }
}

and

record Test(int hello);

The record definition is shorthand and expands into something that uses init, which is why it's also affected.

The language tracking page I linked to above says the feature was Merged into 16.7p3, which I am using.

Am I just being overly excited? Do I need to wait? Or is there a way to play with these features right now :D

EDIT (requested in comments) - Adding csproj for .net 5.0 console app:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <LangVersion>preview</LangVersion>
  </PropertyGroup>
</Project>

EDIT #2: A workaround posted here - https://github.com/dotnet/roslyn/issues/45510

6
  • are you targetting .net core 5? Commented Jun 29, 2020 at 23:37
  • yes. The problem occurs in both .net 5.0 console app (preview6) and .net standard 2.1 class library.
    – Josh
    Commented Jun 29, 2020 at 23:39
  • .net standard 2.1 won't have that. please post your entire csproj Commented Jun 29, 2020 at 23:40
  • edited the post to include the csproj
    – Josh
    Commented Jun 29, 2020 at 23:42
  • 1
    Anyone know what IsExternalInit means? Just curious.
    – Qwertie
    Commented Dec 12, 2020 at 23:12

4 Answers 4

109

This is a bug in the current preview and the latest master branch (June 27). A simple record in sharplab.io creates the same error.

Just add the missing type somewhere in your project

using System.ComponentModel;

namespace System.Runtime.CompilerServices
{
    [EditorBrowsable(EditorBrowsableState.Never)]
    internal class IsExternalInit{}
}

Records and init will work without problem.

Only LinqPad 6 seems to work without problems, probably because it includes that type too

11
  • 3
    I had this error when TargetFramework netstandard2.0 with LangVersion 9.0. This class made it work. Commented Sep 2, 2020 at 7:38
  • 3
    I have 5.0 release version and it's still a problem wtf Commented Dec 1, 2020 at 17:29
  • 2
    @PanagiotisKanavos: I experienced the same as you (having only one .NET 5.0 project out of a lot others that got this trouble on the records declaration). I found out that it happens on projects that have a reference to other projects where .NET Standard 2.0 is being used along with C#9.0 features like the "records" one. If I removed this project from the references, error goes away. As soon as I re-add the reference to the project, it reappears. It doesn't matter if you already added the class in the old project, you have to add it on current one as well.
    – CesarD
    Commented Jan 13, 2021 at 18:57
  • 2
    Very important: do not put #if around this declaration. See twitter.com/aarnott/status/1362786409954766858 for details. Also, make it internal. Commented Feb 19, 2021 at 16:37
  • 1
    There is a package that provides this and other classes that are required to make new C# features work in older target frameworks: PolySharp
    – cremor
    Commented Jan 19, 2023 at 6:45
22

If you don't like to litter each and every project with the IsExternalInit class, you can use Directory.Build.props to automatically reference the file as an invisible compile item:

<?xml version="1.0" encoding="utf-8"?>
<Project>
    <ItemGroup>
        <Compile Include="$(MSBuildThisFileDirectory)IsExternalInit.cs" Visible="false" />
    </ItemGroup>
</Project>

Add/edit this file in your solution's root and add the IsExternalInit.cs file there as well. Doing so will add that file to all your projects automatically.

Example folder structure relative to your solution:

.
├── Directory.Build.props
├── IsExternalInit.cs
└── Solution.sln
3
  • 1
    Nice answer but it needs to be explained better : 1 - In your root folder (solution folder). Create a file Directory.Build.props where *.pros is its extension. 2 - Edit this file and add : <?xml version="1.0" encoding="utf-8"?> <Project> <ItemGroup> <Compile Include="$(MSBuildThisFileDirectory)IsExternalInit.cs" Visible="false" /> </ItemGroup> </Project> 3 - Add the IsExternalInit.cs file alongside
    – abdelgrib
    Commented Feb 4, 2022 at 9:48
  • This works for MSBuild, but VS even with a successful build inline-marks it as an error anyway? (targeting .NET FW, LangVersion 9.0)
    – Kissaki
    Commented Apr 7, 2022 at 15:31
  • @Kissaki I don't get IntelliSense issues on the init keyword in Visual Studio 2022.
    – Bouke
    Commented Oct 11, 2022 at 18:56
16

Borrowing from Panagiotis Kanavos, you can actually declare IsExternalInit as a record itself (self fulfilling prophecy):

using System.ComponentModel;

namespace System.Runtime.CompilerServices
{
    [EditorBrowsable(EditorBrowsableState.Never)]
    public record IsExternalInit;
}
4
  • 1
    Can you explain why you would do this?
    – HackSlash
    Commented Apr 4, 2023 at 17:21
  • Because it still solves the problem and feels like the perfect balance between genius and stupid.
    – mycroes
    Commented Apr 5, 2023 at 5:26
  • Ok, I'm asking what benefit there is to public record over internal class. It seems to only reduce the type scope to record types while increasing the visibility scope to be external. Is that desirable?
    – HackSlash
    Commented Apr 5, 2023 at 15:30
  • The differences are negligible. As far as scope is concerned, choose what works best for you. I sometimes use this in a project that's referenced by almost any other project in the solution, in that case public avoids the need of copying. records are basically classes, so choose whatever you prefer.
    – mycroes
    Commented Apr 5, 2023 at 20:15
5

Nice answer of @Brouke, I'll juste explain more :

1 - In your root folder (solution folder), create a file called Directory.Build.props where *.props is its extension.

2 - Edit this file and add :

<?xml version="1.0" encoding="utf-8"?>
<Project>
    <ItemGroup>
        <Compile Include="$(MSBuildThisFileDirectory)IsExternalInit.cs" Visible="false" />
    </ItemGroup>
</Project>

3 - Add the IsExternalInit.cs file alongside, with :

using System.ComponentModel;

namespace System.Runtime.CompilerServices
{
    [EditorBrowsable(EditorBrowsableState.Never)]
    public record IsExternalInit;
}

4 - Delete all other IsExternalInit.cs files, rebuild solution and restart VS.

2
  • 1
    In case you're adding it to every project in the solution, it doesn't make sense to have it public.
    – mycroes
    Commented Jul 31, 2023 at 20:49
  • 1
    You mean .props not .pros right?
    – corix010
    Commented Nov 30, 2023 at 21:48

Not the answer you're looking for? Browse other questions tagged or ask your own question.