Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
C# 14 and .NET 10 – Modern Cross-Platform Development Fundamentals

You're reading from   C# 14 and .NET 10 – Modern Cross-Platform Development Fundamentals Build modern websites and services with ASP.NET Core, Blazor, and EF Core using Visual Studio 2026

Arrow left icon
Product type Paperback
Published in Nov 2025
Publisher Packt
ISBN-13 9781836206637
Length 828 pages
Edition 10th Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Mark  J. Price Mark J. Price
Author Profile Icon Mark J. Price
Mark J. Price
Arrow right icon
View More author details
Toc

Table of Contents (19) Chapters Close

Preface 1. Hello, C#! Welcome, .NET! 2. Speaking C# FREE CHAPTER 3. Controlling Flow, Converting Types, and Handling Exceptions 4. Writing, Debugging, and Testing Functions 5. Building Your Own Types with Object-Oriented Programming 6. Implementing Interfaces and Inheriting Classes 7. Packaging and Distributing .NET Types 8. Working with Common .NET Types 9. Working with Files, Streams, and Serialization 10. Working with Data Using Entity Framework Core 11. Querying and Manipulating Data Using LINQ 12. Introducing Modern Web Development Using .NET 13. Building Websites Using ASP.NET Core 14. Building Interactive Web Components Using Blazor 15. Building and Consuming Web Services 16. Unlock Your Exclusive Benefits 17. Epilogue 18. Index

Building console apps and managing multiple projects in a solution

The goal of this section is to showcase how to build a console app using Visual Studio.

If you do not have a Windows computer or want to use VS Code, then you can skip this section, since the code will be the same; just the tooling experience is different. However, I recommend that you review this section because it does explain some of the code and how top-level programs work, and that information applies to all code editors.

This section is also available in the GitHub repository (so it can be updated after publishing if needed) at the following link:

https://github.com/markjprice/cs14net10/blob/main/docs/code-editors/vs.md.

If you do not have a Windows computer, or you do not want to use Visual Studio, then you can read similar instructions for using VS Code or Rider. They are available in the GitHub repository at the following links:

https://github.com/markjprice/cs14net10/blob/main/docs/code-editors/vscode.md and

https://github.com/markjprice/cs14net10/blob/main/docs/code-editors/rider.md.

Building .NET projects using Visual Studio

Let’s get started creating a new .NET project and then writing code using Visual Studio:

  1. Start Visual Studio.
  2. In the Create a new project dialog, select the C# language to filter the project templates, enter console in the Search for templates box, and then select Console App.

Make sure that you have chosen the cross-platform project template, not the one for .NET Framework, which is Windows-only, and the C# project template rather than another language, such as Visual Basic or TypeScript.

  1. Click Next.
  2. In the Configure your new project dialog, enter HelloCS for the project name, C:\cs14net10 for the location, and Chapter01 for the solution name.

Screenshots of Visual Studio when creating new projects can be found in the GitHub repository at the following link: https://github.com/markjprice/cs14net10/blob/main/docs/ch01-project-options.md.

  1. Click Next.
  2. In the Additional information dialog, in the Framework drop-down list, note that your .NET SDK choices indicate if that version is Standard Term Support, Long Term Support, Preview, or Out of support, and then select .NET 10.0 (Long Term Support).

    You can install as many .NET SDK versions as you like. If you are missing a .NET SDK version, then you can install it from the following link: https://dotnet.microsoft.com/en-us/download/dotnet.

  1. Leave the checkboxes labeled Enable container support, Do not use top-level statements, and Enable native AOT publish cleared. (You will learn about these other options later in this and other chapters.)
  2. Click Create.
  3. If you cannot see Solution Explorer, then navigate to View | Solution Explorer.
  4. If code is not shown, then in Solution Explorer, double-click the file named Program.cs to open it, and note that Solution Explorer shows the HelloCS project, as shown in Figure 1.6:
Figure 1.6: Editing Program.cs in Visual Studio

Figure 1.6: Editing Program.cs in Visual Studio

  1. In Program.cs, note that the code consists of only a comment and a single statement, as shown in the following code:
    // See https://aka.ms/new-console-template for more information
    Console.WriteLine("Hello, World!");
    

This template uses the top-level program feature introduced in C# 9, which I will explain later in this chapter. As the comment in the code says, you can read more about this template at the following link: https://aka.ms/new-console-template.

  1. In Program.cs, modify line 2 so that the text that is being written to the console says Hello, C#!.

    All code examples and commands that you must review or type are shown in plain text, so you will never have to read code or commands from a screenshot, like in Figure 1.6, which might be too small or too faint in print.

Compiling and running code using Visual Studio

The next task is to compile and run the code:

  1. In Visual Studio, navigate to Debug | Start Without Debugging.
  2. The output in the console window will show the result of running your application, as shown in Figure 1.7:
Figure 1.7: Running the console app on Windows

Figure 1.7: Running the console app on Windows

Your output may look different depending on your command prompt or terminal and its configuration. To change colors with the legacy command prompt app, click the top-left icon, and then in the menu, click Properties, and you will see tabs to change Colors, Font, and so on. You can also install and use alternative command prompts or terminals. For example, I installed Windows Terminal several years ago, and that’s what you can see in Figure 1.7. Since October 2022, Windows Terminal has been the default in Windows 11, so you should not need to install it. But if you use an older version of Windows, then you can install Windows Terminal from the Microsoft Store. You can learn more about Windows Terminal at the following link: https://devblogs.microsoft.com/commandline/windows-terminal-is-now-the-default-in-windows-11/.

  1. Press any key to close the console app window and return to Visual Studio.
  2. In Solution Explorer, double-click the HelloCS project (or right-click the HelloCS project and click Edit Project File), and note that the HelloCS.csproj project file shows that this project has its target framework set to net10.0, as shown in Figure 1.8.

    Although Visual Studio hides the .csproj file extension, the project name in Solution Explorer represents a file named HelloCS.csproj. If you ever need to edit this project file, you can just double-click the project name.

  1. In the Solution Explorer toolbar, toggle on the Show All Files button , and note that the compiler-generated bin and obj folders are visible, as shown in Figure 1.8:
Figure 1.8: Showing the compiler-generated folders and files

Figure 1.8: Showing the compiler-generated folders and files

Attaching the debugger in Visual Studio

When you start a project in Visual Studio, you can choose whether to attach a debugger or not.

If you do not need to debug, then it is better not to attach one because attaching a debugger requires more resources and slows everything down.

Attaching a debugger also limits you to only starting one project. If you want to run more than one project, each with a debugger attached, then you must start multiple instances of Visual Studio (one benefit of Rider is that it doesn’t have this limitation).

Another reason to start without debugging is that if you start a console app with the debugger attached, by default, it will automatically close the console window before you can read it.

To disable this behavior, follow these steps:

  1. Navigate to Tools | Options | Debugging | General.
  2. Clear the Automatically close the console when debugging stops checkbox.

Good practice: To start without debugging, instead of the green solid triangle button (to the left of HelloCS in the top bar shown in Figure 1.7), click the green outline triangle button unless you really need to debug.

Understanding the compiler-generated folders and files

Two compiler-generated folders were created, named obj and bin, as described in the following list:

  • The obj folder contains one compiled object file for each source code file. These objects haven’t been linked together into a final executable yet.
  • The bin folder contains the binary executable for the application or class library. We will look at this in more detail in Chapter 7, Packaging and Distributing .NET Types.

You do not need to look inside these folders or understand all their files (but feel free to browse around if you are curious). At this point, the main thing that you need to understand is that the compiler needs to create temporary folders and files to do its work. You could delete these folders and their files, and they will be automatically recreated the next time you “build” or run the project. Most .NET developers never need to know the details of what most of these files do. You will never need to work with them directly.

Warning! Files that use .g. in their filename indicate that they are “generated” by the build process. You should never edit these files because they will just get recreated the next time you build.

Developers often delete these temporary folders and files to “clean” a project. Visual Studio even has a command on the Build menu named Clean Solution that deletes some of these temporary files for you. The equivalent command with the CLI is dotnet clean.

A tool that runs dotnet clean for each target framework and configuration and then deletes the output directories, and can be run in a directory containing a solution or project file, is found at the following link: https://github.com/DamianEdwards/dotnet-purge.

Understanding top-level programs

If you have seen older .NET projects before, then you might have expected more code, even just to output a simple message. This project has minimal statements because some of the required code is written for you by the compiler when you target .NET 6 or later.

If you had created the project with .NET SDK 5 or earlier, or if you had selected the checkbox labeled Do not use top-level statements, then the Program.cs file would have more statements, as shown in the following code:

using System;
namespace HelloCS
{
  class Program
  {
    static void Main(string[] args)
    {
      Console.WriteLine("Hello, World!");
    }
  }
}

During compilation with .NET SDK 6 or later, all the boilerplate code to define the Program class and its Main method is generated and wrapped around the statements you write.

This uses a feature introduced in .NET 5 called top-level programs, but it was not until .NET 6 that Microsoft updated the project template for console apps to use top-level statements by default. Then, in .NET 7 and later, Microsoft added options to use the older style if you prefer:

  • If you are using Visual Studio, select the checkbox labeled Do not use top-level statements
  • If you are using the dotnet CLI at the command prompt, add a switch:
    dotnet new console --use-program-main
    

Warning! One functional difference is that the auto-generated code does not define a namespace, so the Program class is implicitly defined in an empty namespace with no name, instead of a namespace that matches the name of the project.

Requirements for top-level programs

Key points to remember about top-level programs include the following:

  • There can be only one file, like the file you use for top-level program code in a project
  • Any using statements must be at the top of the file
  • If you declare any classes or other types, they must be at the bottom of the file
  • Although you should name the entry-point method Main if you explicitly define it, the method is named <Main>$ when created by the compiler

Implicitly imported namespaces

The using System; statement at the top of the file imports the System namespace. This enables the Console.WriteLine statement to work. But why do we not have to import it into our project?

The trick is that we still need to import the System namespace, but it is now done for us using a combination of features introduced in C# 10 and .NET 6. Let’s see how:

  1. In Solution Explorer, expand the obj, Debug, and net10.0 folders, and open the file named HelloCS.GlobalUsings.g.cs.
  2. Note that this file is automatically created by the compiler for projects that target .NET 6 or later and uses a feature introduced in C# 10, called global namespace imports, which imports some commonly used namespaces like System for use in all code files, as shown in the following code:
    // <autogenerated />
    global using System;
    global using System.Collections.Generic;
    global using System.IO;
    global using System.Linq;
    global using System.Net.Http;
    global using System.Threading;
    global using System.Threading.Tasks;
    
  3. In Solution Explorer, toggle off the Show All Files button to hide the bin and obj folders.

I will explain more about the implicit imports feature in the next chapter. For now, just note that a significant change that happened between .NET 5 and .NET 6 is that many of the project templates, like the one for console apps, use the new SDK and language features to hide what is really happening.

Revealing the hidden code by throwing an exception

Now, let’s discover how the hidden code that will be autogenerated by the top-level program feature has been written:

  1. In Program.cs, after the statement that outputs the message, add a statement to throw a new exception, as shown in the following code:
    throw new Exception();
    
  2. In Visual Studio, navigate to Debug | Start Without Debugging. (Do not start the project with debugging, or the exception will be caught by the debugger!)
  3. The output in the console window will show the result of running your application, including that a hidden Program class was defined by the compiler, with a method named <Main>$ that has a parameter named args to pass in arguments, as shown in Figure 1.9 and the following output:
    Hello, C#!
    Unhandled exception. System.Exception: Exception of type 'System.Exception' was thrown.
       at Program.<Main>$(String[] args) in C:\cs14net10\Chapter01\HelloCS\Program.cs:line 3
    
Figure 1.9: Throwing an exception to reveal the hidden Program.<Main>$ method

Figure 1.9: Throwing an exception to reveal the hidden Program.<Main>$ method

  1. Press any key to close the console app window and return to Visual Studio.

Revealing the namespace for the Program class

Now, let’s discover what namespace the Program class has been defined within:

  1. In Program.cs, before the statement that throws an exception, add statements to get the name of the namespace of the Program class, and then write it to the console, as shown in the following code:
    string name = typeof(Program).Namespace ?? "<null>";
    Console.WriteLine($"Namespace: {name}");
    

?? is the null-coalescing operator. The first statement means, “If the namespace of Program is null, then return <null>; otherwise, return the actual name.” You will see more explanations of these keywords and operators throughout the book. For now, just enter the code and run it to see what it does.

Good practice: Code editors have a feature named code snippets. These allow you to insert pieces of code that you commonly use by typing a shortcut and pressing Tab or Enter. For example, in Visual Studio, to enter Console.WriteLine() and leave the cursor in the middle of the parentheses ready for you to type what you want to output, type cw, and then press Tab or Enter. Read the documentation for your code editor to learn how to insert code snippets using shortcuts.

  1. In Visual Studio, navigate to Debug | Start Without Debugging.
  2. The output in the console window will show the result of running your application, including that the hidden Program class was defined without a namespace, as shown in the following output:
    Namespace: <null>
    
  3. Press any key to close the console app window and return to Visual Studio.

Adding a second project using Visual Studio

Let’s add a second project to our solution to explore how to work with multiple projects:

  1. In Visual Studio, navigate to File | Add | New Project….

Warning! The preceding step adds a new project to the existing solution. Do NOT navigate to File | New | Project…, which instead is meant to be used to create a new project and solution (although the dialog box has a dropdown to choose to add to an existing solution too).

  1. In the Add a new project dialog, in Recent project templates, select Console App, and then click Next.
  2. In the Configure your new project dialog, for Project name, enter AboutMyEnvironment, leave the location as C:\cs14net10\Chapter01, and then click Next.
  3. In the Additional information dialog, select .NET 10.0 (Long Term Support), leave the Enable container support and Enable native AOT publish checkboxes cleared, and select the Do not use top-level statements checkbox.

Warning! Make sure you have selected the Do not use top-level statements checkbox so that we get to see the older style of Program.cs.

  1. Click Create.
  2. In the AboutMyEnvironment project, in Program.cs, note the statements to define a namespace that matches the project name, an internal class named Program, and a static method named Main with a parameter named args that returns nothing (void), as shown in the following code:
    namespace AboutMyEnvironment
    {
      internal class Program
      {
        static void Main(string[] args)
        {
          Console.WriteLine("Hello, World!");
        }
      }
    }
    
  3. In Program.cs, in the Main method, replace the existing Console.WriteLine statement with statements to output the current directory, the version of the operating system, and the namespace of the Program class, as shown in the following code:
    Console.WriteLine(Environment.CurrentDirectory);
    Console.WriteLine(Environment.OSVersion.VersionString);
    Console.WriteLine("Namespace: {0}",
      typeof(Program).Namespace ?? "<null>");
    
  4. In Solution Explorer, right-click the Chapter01 solution, and then select Configure Startup Projects….
  5. In the Solution ‘Chapter01’ Property Pages dialog box, set Startup Project to Current selection, and then click OK.
  6. In Solution Explorer, click the AboutMyEnvironment project (or any file or folder within it), and note that Visual Studio indicates that AboutMyEnvironment is now the startup project by making the project name bold.

Good practice: I recommend this way of setting the startup project because it then makes it very easy to switch startup projects by simply clicking a project (or any file in a project) to make it the startup project. Although you can right-click a project and set it as a startup project, if you then want to run a different project, you must manually change it again. Simply clicking anywhere in the project is easier. In most chapters, you will only need to run one project at a time. In Chapter 15, Building and Consuming Web Services, I will show you how to configure multiple startup projects.

  1. Navigate to Debug | Start Without Debugging to run the AboutMyEnvironment project, and note the result, as shown in the following output and Figure 1.10:
    C:\cs14net10\Chapter01\AboutMyEnvironment\bin\Debug\net10.0
    Microsoft Windows NT 10.0.26100.0
    Namespace: AboutMyEnvironment
    
Figure 1.10: Running a console app in a Visual Studio solution with two projects

Figure 1.10: Running a console app in a Visual Studio solution with two projects

Windows 11 is just branding. Its official name is Windows NT, and its major version number is still 10! But its patch version is 22000 or higher.

  1. Press any key to close the console app window and return to Visual Studio.

When Visual Studio runs a console app, it executes it from the <projectname>\bin\Debug\net10.0 folder. It will be important to remember this when we work with the filesystem in later chapters.

When using VS Code, or more accurately, the dotnet CLI, it has different behavior, as you will see if you complete the optional online section about writing code with VS Code, found at the following link: https://github.com/markjprice/cs14net10/blob/main/docs/code-editors/vscode.md.

Now, let’s see how you can use the GitHub repository for this book.

lock icon The rest of the chapter is locked
Visually different images
CONTINUE READING
83
Tech Concepts
36
Programming languages
73
Tech Tools
Icon Unlimited access to the largest independent learning library in tech of over 8,000 expert-authored tech books and videos.
Icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Icon 50+ new titles added per month and exclusive early access to books as they are being written.
C# 14 and .NET 10 – Modern Cross-Platform Development Fundamentals
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Modal Close icon
Modal Close icon