This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.
This week saw the release of .NET Standard 2.0. According to the announcement, I’ll have to wait until “later this year” to use it in the Time Tortoise UWP project. But I thought it would be a good time to discuss some related topics that have come up in recent weeks as I’ve been adding to the Time Tortoise solution.
Visual Studio organizes code in projects, which can be collected together in a solution. When you create a new project, Visual Studio first asks that you specify a project type. It uses this type to select a template which defines characteristics of the project and a starting set of code files.
The Time Tortoise solution now contains a total of 12 projects of these types:
- A .NET Core Console App for manually testing the .NET Core class libraries.
- A Windows Classic Desktop console app for manually testing the Windows Classic Desktop class library.
- Seven .NET Core/.NET Standard class libraries.
- A Windows Classic Desktop class library (TimeTortoise.Server)
- A Windows Presentation Foundation (WPF) app, the host app for Time Tortoise Companion.
- A Universal Windows Platform (UWP) app, the host app for Time Tortoise itself.
This week, I’ll be focusing on the .NET Core/.NET Standard class libraries.
.NET Core Class Libraries
A class library project compiles to an assembly (.NET DLL) that other projects can reference. For example, the Time Tortoise UWP project references the class library
TimeTortoise.ViewModel, which contains classes that support the user interface.
Class libraries are convenient for unit testing because they’re designed to be called by other code. There’s no user interface to make testing difficult, as with console or UWP app projects. So my policy for Time Tortoise is to put as much code as possible in class libraries.
UWP apps can’t reference Windows Classic Desktop class libraries. Those can only be used by WPF and other pre-UWP project types. For UWP apps, we need to use .NET Core class libraries.
.NET Standard vs. .NET Core
The .NET Standard is a “formal specification,” while .NET Core is one particular implementation of the standard. Or in OOP terms, .NET Standard is like an interface and .NET Core is like a concrete implementation of that interface.
One thing to keep in mind about this definition is that Visual Studio provides class library project types for both .NET Core and .Net Standard. So for a class library, you can choose to target either one. By targeting .NET Core, you get access to a bit more functionality, but some of that functionality may not be compatible with other .NET Standard implementations. Choosing the .NET Standard class library project type ensures that you’ll only use functionality that every .NET Standard implementation supports.
Class Library Project Types in Visual Studio
One way to learn about project types is to examine what they look like in Visual Studio Solution Explorer. As an experiment, I created one of each of these class library project types in Visual Studio 2017:
Windows Classic Desktop Class Library
This is the traditional class library that has been available since the early days of .NET. It has the following sections:
- A Properties section containing AssemblyInfo.cs, a class with information about the assembly.
- A References section with default references, including System, System.Core, System.Data, and others.
- Class1.cs, an empty class with default
The components of the project (files, references, and other information) for this project type are stored in a
In this project type, the References section has been renamed to Dependencies. The section has a reference to
Microsoft.NETCore.App, which contains a long list of core assemblies, including System.Collections.Immutable, System.Linq.Expressions, and many others.
The Properties section has been removed, and the default class file refers only to
.csproj file is used, but it starts out very small compared to the classic csproj. As properties are modified from their default values, sections are added to the csproj. Another csproj change for .NET Core: project files don’t need to be explicitly referenced. Instead, they show up in Solution Explorer as soon as they are created in the project directory.
The difference between the .NET Standard and .NET Core project types is that the .NET Standard project type references a dependency called
NETStandard.Library, with a different set of standard assemblies.
Portable Class Library
This project type has been deprecated as of .NET Standard 2.0. It contains Properties and References sections like the Classic type, and a verbose
.csproj file. But it also uses a file called
project.json that is referenced in the csproj, and defines frameworks, dependencies, and supported environments.
One More Type, as Used By the Time Tortoise Solution
I started Time Tortoise development at the beginning of 2017, before Visual Studio 2017 was out of beta. I also had some specific requirements for class libraries that could be both tested by xUnit.NET and referenced by a UWP project. As described in my first unit testing post, the following approach was the one that worked best for creating class library projects:
- Create a Portable Class Library project.
- In Project Properties, click Target .NET Platform Standard.
The result is a project that looks like a Portable Class Library project. It has Properties and References section, a project.json file, and even a (Portable) designation appended to the project name in Solution Explorer. But it targets
For now, this configuration is working well, even now that I have added classic project types to the solution for Time Tortoise Companion. But I should ideally just target .NET Standard directly, without starting with a Portable Class Library. A good time to try out this change will be later in 2017 when UWP supports .NET Standard 2.0. At that time, I’ll try recreating the class library projects as .NET Standard 2.0 projects, and see if everything still works.