Update (2021-10-14)
Mark Rendle made an interesting suggestion on Twitter after seeing this blog post. I've updated the post below with his code.
Yesterday I livestreamed myself upgrading a project to .NET 6 and C# 10. Along the way I tried using a new C# 10 feature called implicit using statements and discovered that it wasn't quite as straightforward as I first thought and you should probably not use it under certain circumstances.
Here is the live stream for those who are interested (I'm eager to get any feedback on how I'm presenting as its not a natural skill for me):
What are Implicit Using Statements?
Adding the line below to your .csproj
project file turns the feature on:
<ImplicitUsings>enable</ImplicitUsings>
Once enabled, depending on the type of project you have created you'll have the following global using statements added to your project implicitly.
SDK | Default namespaces |
---|---|
Microsoft.NET.Sdk | System System.Collections.Generic System.IO System.Linq System.Net.Http System.Threading System.Threading.Tasks |
Microsoft.NET.Sdk.Web | System.Net.Http.Json Microsoft.AspNetCore.Builder Microsoft.AspNetCore.Hosting Microsoft.AspNetCore.Http Microsoft.AspNetCore.Routing Microsoft.Extensions.Configuration Microsoft.Extensions.DependencyInjection Microsoft.Extensions.Hosting Microsoft.Extensions.Logging |
Microsoft.NET.Sdk.Worker | Microsoft.Extensions.Configuration Microsoft.Extensions.DependencyInjection Microsoft.Extensions.Hosting Microsoft.Extensions.Logging |
Sounds great, now you can delete a large portion of the using statements in your project right? Well not so fast, here are some problems I discovered along the way.
Build Errors
I discovered the first problem while multi-targetting a class library project for a NuGet package. I had targetted .NET 4.7.2 as well as other target frameworks like .NET 6 for backwards compatibility and found that System.Net.Http
could not be found. It turns out I hadn't referenced that particular NuGet package for .NET 4.7.2 and was now getting a build error.
I could add the System.Net.Http
NuGet package for .NET 4.7.2 on its own and that would solve the problem but I really didn't like having the overhead of another unnecessary package reference. That also means extra work for me to maintain updating the version number or relying on tools like Dependabot and Renovate to submit PR's to upgrade the version number for me.
<ItemGroup Label="Package References (.NET 4.7.2)" Condition="'$(TargetFramework)' == 'net472'">
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>
Mark Rendle on Twitter suggested another workaround after seeing this blog post. His suggestion was to remove the offending using statement in the .csproj
file.
<ItemGroup>
<Using Remove="System.Net.Http" />
</ItemGroup>
This looks awfully strange to me. I'm not sure how I feel about adding or removing namespaces from C# project files yet. It doesn't seem very discoverable to me. So in this particular case I'm happy to avoid using implicit using statements for now.
What Using's Were Added?
The second problem is trying to understand what using's have been added. As you can see from the table above, you could go and look in the documentation to figure this out but that's slow and time consuming. Another alternative is actually to build your project and then look in its obj
directory under:
My.Project\obj\Debug\net472\My.Project.GlobalUsings.g.cs
That's not ideal either. I think Visual Studio should ideally show you these using statements somehow.
Conclusions
Implicit usings are enabled by default in the latest blank project templates shipped with .NET. Overall this is a cool feature that can remove the need for many duplicated lines of code in your project but I think there is a little too much magic going on here for my liking, so I think I'll be more careful about using this feature in the future.
Comment
Initializing...