If .NET Core 2 was the first real version of .NET Core, then 3.0/3.1 took something usable and made it solid. With their latest version, Microsoft went from “good enough” to something enjoyable to use. .NET 3.0/3.1 closed a lot of the gaps left between .NET Framework and .NET Core. Not all of the gaps, but many.
.NET Core 3 added support for things such as WPF (Windows Presentation Foundation), a UI framework used to build Windows desktop applications. .NET Core 3 also added support for Windows Forms, which, in my opinion, is one of the easiest to use UI frameworks ever created. It was a pretty big miss for Windows desktop application developers to not have access to .NET Core, but .NET 3 fixed that.
Another significant change with .NET Core 3 was support for multiple return items from a single method. You could always work around this by just returning an object that encompasses data you want to return. This new language feature prevents having to create some wrapper objects. In previous versions, you could get away without creating wrapper objects by using the Tuples class, but this new language cleans up the syntax and usage.
Another change that I appreciate is how using statements works. Prior to .NET Core 3, a using statement always included some brackets, and the variable declared inside the using statement was only available inside the brackets. While this makes complete sense, I think it creates unnecessary brackets. And with each set of brackets, you get another level of indenting. While not necessarily a problem, the new syntax cleans up the code. Much like var from early .NET changes, this one simplifies and cleans up a lot of code.
.NET Core 3 was a quality release that smoothed a lot of rough edges.
.NET Framework 2.0 (Generics, Partial Classes, Nullable Types, Anonymous Methods)
.NET Framework 3.0/3.5 (WPF, WF, WCF, Auto-Implemented Properties)
.NET Framework 3.0 (LINQ)
.NET Framework 3.5 SP1 (ADO.NET Entity Framework)
.NET Framework 4.0 (Parallel, Dynamic)
.NET Framework 4.5 (Async)
.NET Core 2.0/2.1
.NET Core 3.0/3.1
.NET Core 5.0