Discover millions of ebooks, audiobooks, and so much more with a free trial

From $11.99/month after trial. Cancel anytime.

Code like a Pro in C#
Code like a Pro in C#
Code like a Pro in C#
Ebook827 pages7 hours

Code like a Pro in C#

Rating: 0 out of 5 stars

()

Read preview

About this ebook

Build on your existing programming skills and upskill to professional-level C# programming.

Summary
In Code Like A Pro in C# you will learn:

    Unit testing and test-driven development
    Refactor a legacy .NET codebase
    Principles of clean code
    Essential backend architecture skills
    Query and manipulate databases with LINQ and Entity Framework Core

Critical business applications worldwide are written in the versatile C# language and the powerful .NET platform, running on desktops, cloud systems, and Windows or Linux servers. Code Like a Pro in C# makes it easy to turn your existing abilities in C# or another OO language (such as Java) into practical C# mastery. There’s no “Hello World” or Computer Science 101 basics—you’ll learn by refactoring an out-of-date legacy codebase, using new techniques, tools, and best practices to bring it up to modern C# standards.

Purchase of the print book includes a free eBook in PDF, Kindle, and ePub formats from Manning Publications.

About the technology
You know the basics, now get ready for the next step! Pro-quality C# code is efficient, clean, and fast. Whether you’re building user-facing business applications or writing data-intensive backend services, the experience-based, practical techniques in this book will take your C# skills to a new level.

About the book
Code Like a Pro in C# teaches you to how write clean C# code that’s suitable for enterprise applications. In this book, you’ll refactor a legacy codebase by applying modern C# techniques. You’ll explore tools like Entity Framework Core, design techniques like dependency injection, and key practices like testing and clean coding. It’s a perfect path to upgrade your existing C# skills or shift from another OO language into C# and the .NET ecosystem.

What's inside

    Unit testing and test-driven development
    Refactor a legacy .NET codebase
    Principles of clean code
    Query and manipulate databases with LINQ and Entity Framework Core

About the reader
For developers experienced with object-oriented programming. No C# experience required.

About the author
Jort Rodenburg is a software engineer who has taught numerous courses on getting up to speed with C# and .NET.

Table of Contents

PART 1 USING C# AND .NET
1 Introducing C# and .NET
2 .NET and how it compiles
PART 2 THE EXISTING CODEBASE
3 How bad is this code?
4 Manage your unmanaged resources!
PART 3 THE DATABASE ACCESS LAYER
5 Setting up a project and database with Entity Framework Core
PART 4 THE REPOSITORY LAYER
6 Test-driven development and dependency injection
7 Comparing objects
8 Stubbing, generics, and coupling
9 Extension methods, streams, and abstract classes
PART 5 THE SERVICE LAYER
10 Reflection and mocks
11 Runtime type checking revisited and error handling
12 Using IAsyncEnumerable and yield return
PART 6 THE CONTROLLER LAYER
13 Middleware, HTTP routing, and HTTP responses
14 JSON serialization/deserialization and custom model binding
LanguageEnglish
PublisherManning
Release dateAug 24, 2021
ISBN9781638356417
Code like a Pro in C#

Related to Code like a Pro in C#

Related ebooks

Programming For You

View More

Related articles

Reviews for Code like a Pro in C#

Rating: 0 out of 5 stars
0 ratings

0 ratings0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    Book preview

    Code like a Pro in C# - Jort Rodenburg

    inside front cover

    Clean Code Checklist

    Use this short checklist when encountering code that you are unfamiliar with or while writing new code.

    General

    ✓ My code reads like a narrative. I write code for humans, not machines.

    ✓ I document my code only when necessary. My code should speak for itself.

    ✓ I provide clear instructions on how to build and release my codebase. Where appropriate, I provide working build scripts/makefiles or CI/CD setup instructions.

    ✓ I use native functionalities instead of implementing my own libraries, unless for a very good reason.

    ✓ My code is consistent in its design patterns, documentation, and naming conventions. I do not change things mid-development and go against established patterns.

    ✓ I have added logging to my application, so I or other developers can debug when things go awry.

    Classes

    ✓ My class has the strictest access modifier possible.

    ✓ My class is named accurately.

    ✓ My class performs operations on only one specific object and, therefore, adheres to the single-responsibility principle.

    ✓ My class lives in the right folder within my project.

    ✓ If I struggle with implementing my class, I take a step back and come up with a brief description of the class and its intended functionality. This refocus can help write cleaner code. If my class should do multiple things, split it up.

    Methods

    ✓ My method has the strictest access modifier possible.

    ✓ My method is named accurately and correctly describes the logic within (leaving nothing out).

    ✓ My method performs only one general operation or collects information from other methods related to its operations. It adheres to the single-responsibility principle.

    ✓ If my method has a public access modifier, we do not perform any operations within the method. The public method calls other, smaller, methods and organizes the outputs.

    ✓ I have unit tests backing my method. The unit tests should cover the major success and failure logic branches.

    Continues on inside back cover

    Code like a Pro in C#

    Jort Rodenburg

    To comment go to liveBook

    Manning

    Shelter Island

    For more information on this and other Manning titles go to

    www.manning.com

    Copyright

    For online information and ordering of these  and other Manning books, please visit www.manning.com. The publisher offers discounts on these books when ordered in quantity.

    For more information, please contact

    Special Sales Department

    Manning Publications Co.

    20 Baldwin Road

    PO Box 761

    Shelter Island, NY 11964

    Email: [email protected]

    ©2021 by Manning Publications Co. All rights reserved.

    No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher.

    Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademark claim, the designations have been printed in initial caps or all caps.

    ♾ Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end. Recognizing also our responsibility to conserve the resources of our planet, Manning books are printed on paper that is at least 15 percent recycled and processed without the use of elemental chlorine.

    ISBN: 9781617298028

    contents

    preface

    acknowledgments

    about this book

    about the author

    about the cover illustration

    Part 1  Using C# and .NET

      1  Introducing C# and .NET

    1.1  Why work in C#?

    Reason 1: C# is economical

    Reason 2: C# is maintainable

    Reason 3: C# is developer friendly and easy to use

    1.2  Why not work in C#?

    Operating system development

    Real-time operating system embedded development in C#

    Numerical computing and C#

    1.3  Switching to C#

    1.4  What you will learn in this book

    1.5  What you will not learn in this book

      2  .NET and how it compiles

    2.1  What is the .NET Framework?

    2.2  What is .NET 5?

    2.3  How CLI-compliant languages are compiled

    Step 1: C# code (high-level)

    Step 2: Common Intermediate Language (assembly level)

    Step 3: Native code (processor level)

    Part 2  The existing codebase

      3  How bad is this code?

    3.1  Introducing Flying Dutchman Airlines

    3.2  Pieces of the puzzle: Taking a look at our requirements

    Object-relational mapping

    The GET /flight endpoint: Retrieving information on all flights

    The GET /flight/{flightNumber} endpoint: Getting specific flight information

    The POST /booking/{flightNumber} endpoint: Booking a flight

    3.3  Coming to terms with the existing codebase

    Assessing the existing database schema and its tables

    The existing codebase: Web service configuration files

    Considering models and views in the existing codebase

      4  Manage your unmanaged resources!

    4.1  The FlightController: Assessing the GET /flight endpoint

    The GET /flight endpoint and what it does

    Method signature: The meaning of ResponseType and typeof

    Collecting flight information with collections

    Connection strings, or how to give a security engineer a heart attack

    Using IDisposable to release unmanaged resources

    Querying a database with SqlCommand

    4.2  The FlightController: Assessing GET /flight/{flightNumber}

    4.3  The FlightController: POST /flight

    4.4  The FlightController: DELETE /flight/{flightNumber}

    Part 3  The database access layer

      5  Setting up a project and database with Entity Framework Core

    5.1  Creating a .NET 5 solution and project

    5.2  Setting up and configuring a web service

    Configuring a .NET 5 web service

    Creating and using HostBuilder

    Implementing the Startup class

    Using the repository/service pattern for our web service architecture

    5.3  Implementing the database access layer

    Entity Framework Core and reverse-engineering

    DbSet and the Entity Framework Core workflow

    Configuration methods and environment variables

    Setting an environment variable on Windows

    Setting an environment variable on macOS

    Retrieving environment variables at run time in your code

    Part 4  The repository layer

      6  Test-driven development and dependency injection

    6.1  Test-driven development

    6.2  The CreateCustomer method

    Why you should always validate input arguments

    Using arrange, act, assert to write unit tests

    Validating against invalid characters

    In-lining test data with the [DataRow] attribute

    Object initializers and autogenerated code

    Constructors, reflection, and asynchronous programming

    Locks, mutexes, and semaphores

    Synchronous to asynchronous execution . . . continued

    Testing Entity Framework Core

    Controlling dependencies with dependency injection

      7  Comparing objects

    7.1  The GetCustomerByName method

    Question marks: Nullable types and their applications

    Custom exceptions, LINQ, and extension methods

    7.2  Congruence: From the Middle Ages to C#

    Creating a comparer class using EqualityComparer

    Testing equality by overriding the Equals method

    Overloading the equality operator

      8  Stubbing, generics, and coupling

    8.1  Implementing the Booking repository

    8.2  Input validation, separation of concerns, and coupling

    8.3  Using object initializers

    8.4  Unit testing with stubs

    8.5  Programming with generics

    8.6  Providing default arguments by using optional parameters

    8.7  Conditionals, Func, switches, and switch expressions

    The ternary conditional operator

    Branching using an array of functions

    Switch statements and expressions

    Querying for pending changes in Entity Framework Core

      9  Extension methods, streams, and abstract classes

    9.1  Implementing the Airport repository

    9.2  Getting an Airport out of the database by its ID

    9.3  Validating the AirportID input parameter

    9.4  Output streams and being specifically abstract

    9.5  Querying the database for an Airport object

    9.6  Implementing the Flight repository

    The IsPositive extension method and magic numbers

    Getting a flight out of the database

    Part 5  The service layer

    10  Reflection and mocks

    10.1  The repository/service pattern revisited

    What is the use of a service class?

    10.2  Implementing the CustomerService

    Setting up for success: Creating skeleton classes

    How to delete your own code

    10.3  Implementing the BookingService

    Unit testing across architectural layers

    The difference between a stub and a mock

    Mocking a class with the Moq library

    Calling a repository from a service

    11  Runtime type checking revisited and error handling

    11.1  Validating input parameters of a service layer method

    Runtime type checks with the is and as operators

    Type checking with the is operator

    Type checking with the as operator

    What did we do in section 11.1?

    11.2  Cleaning up the BookingServiceTests class

    11.3  Foreign key constraints in service classes

    Calling the Flight repository from a service class

    12  Using IAsyncEnumerable and yield return

    12.1  Do we need an AirportService class?

    12.2  Implementing the FlightService class

    Getting information on a specific flight from the FlightRepository

    Combining two data streams into a view

    Using the yield return keywords with try-catch code blocks

    Implementing GetFlightByFlightNumber

    Part 6  The controller layer

    13  Middleware, HTTP routing, and HTTP responses

    13.1  The controller class within the repository/service pattern

    13.2  Determining what controllers to implement

    13.3  Implementing the FlightController

    Returning HTTP responses with the IActionResult interface (GetFlights)

    Injecting dependencies into a controller using middleware

    Implementing the GET /Flight/{FlightNumber} endpoint

    13.4  Routing HTTP requests to controllers and methods

    14  JSON serialization/deserialization and custom model binding

    14.1  Implementing the BookingController class

    Introduction to data deserialization

    Using the [FromBody] attribute to deserialize incoming HTTP data

    Using a custom model binder and method attribute for model binding

    Implementing the CreateBooking endpoint method logic

    14.2  Acceptance testing and Swagger middleware

    Manual acceptance testing with an OpenAPI specification

    Generating an OpenAPI specification at runtime

    14.3  The end of the road

    appendix A  Exercise answers

    appendix B  Clean code checklist

    appendix C  Installation guides

    appendix D  OpenAPI FlyTomorrow

    appendix E  Reading list

    index

    front matter

    preface

    My first introduction to C# came when I joined Fujifilm Medical Systems in 2016. I had previous experience in Java and Python, but when C# came around, I did not look back. I loved its low barrier of entry and (at first excruciatingly infuriating) focus on explicit typing. Throughout my time at the company, I annoyed my coworkers with questions about C# and how to best use it. Getting started was easy, but becoming proficient was another matter altogether. Everybody can write a Hello, World application within 10 minutes, no matter their background, but using a language to its fullest strengths while knowing why certain things are implemented the way they are simply takes time. After a while, I felt like I had plateaued in my C# knowledge and was looking for resources to take me to the next level. Quickly, I realized that there were three major types of books dealing with .NET and C#: books about language-transcending topics (clean code, architecture, infrastructure, and the like) that happened to use C#, books on how to start programming using C#, and books that are so advanced that you might just be qualified to become the CTO of Microsoft after reading them. I wanted there to be a book that sat in the middle of all three: a book that deals with clean code and bridges the gap between beginner and advanced topics. That book did not exist, so I wrote it. This is that book.

    If you are a software engineer (or developer, or coder, or whatever your title may be) with previous experience in a (preferably object-oriented) programming language and want to jump into C#, this is the book for you. You will not have to learn how to write an if statement, nor will I explain what an object is to you. What you will find in this book are skills and topics that prepare you for deeper study into the language and platform. Of course, I can’t promise to cover everything a more difficult resource assumes you know, but within the limited page count of this book, I sure tried. I very much hope you enjoy this book and learn a thing or two. And if not, well, it never hurts to go over things you know again.

    acknowledgments

    When I first started talking with Manning about writing this book, I had little idea of how it would take over my life for about a year or so. To be fair, I was warned on multiple occasions that authors tend to underestimate the time needed to write a book. I, being stubborn, thought I would be the exception. I was not. From December 2019 to March 2021, I put many hours into this book. On multiple occasions, I thought to myself that this will surely be the end. Every single time (but one, obviously), it was not. Luckily, I have a very patient wife and plenty of time to kill.

    It is with that in mind that I would first like to thank my wife for sticking by me on this roller coaster and to apologize to her for disappearing from her life for a year. I could not have written this book without her unwavering support. She was the rock on which this book was built. I also want to thank my family, who were always very excited to hear about new developments and updates. I took the liberty of naming the CEO of the company in the business case we follow through the book by combining the first name of my maternal grandfather (Aljen) and the surname of my paternal grandmother (van der Meulen).

    I also have to thank the exceptional team at Manning. In particular, I want to single out Marina Michaels. As my editor, she shaped this book into something more than a random collection of incoherent rants. Thanks to Marina, I have developed a healthy fear of using the word will anywhere in writing. I also had a very valuable team in Jean-François Morin, Tanya Wilke, Eric Lippert, Rich Ward, Enrico Buonanno, and Katie Tennant. This intercontinental team of superheroes/ninjas/rockstars provided amazing feedback and caught an immense amount of (often very embarrassing) technical mistakes. I also want to thank all the reviewers and MEAPers who read the manuscript before publication and gave fantastic feedback, often in no uncertain terms. I do not claim this book to be a masterpiece, but I do hope you will get something useful out of it.

    To all the reviewers, thanks: Arnaud Bailly, Christian Thoudahl, Daniel Vásquez Estupiñan, Edin Kapic, Foster Haines, George Thomas, Goetz Heller, Gustavo Filipe Ramos Gomes, Hilde Van Gysel, Jared Duncan, Jason Hales, Jean-François Morin, Jeff Neumann, Karthikeyarajan Rajendran, Luis Moux, Marc Roulleau, Mario Solomou, Noah Betzen, Oliver Korten, Patrick Regan, Prabhuti Prakash, Raymond Cheung, Reza Zeinali, Richard B. Ward, Richard DeHoff, Sau Fai Fong, Slavomir Furman, Tanya Wilke, Thomas F. Gueth, Víctor M. Pérez, and Viktor Bek. Your suggestions helped make this a better book.

    And finally, there are a few people I want to thank for either having helped me with some part of this book or my career in general. First up are David Lavielle and Duncan Henderson: thank you for taking a chance on me and giving me my first job in software development. Jerry Finegan: thanks for introducing me to C# and letting me ask one dumb question after the other. Your patience and feedback were much appreciated. Michael Breecher: you had a hand in shaping some of the content around congruence in this book (forced by my late-night texts asking weird math questions about notation), and the book is better for it. Szymon Zuberek: the first draft of chapter 2 was written in your New York apartment. Thanks for letting us crash on your couch any time we wanted to visit and, as always, for providing conversational fodder. And I thank the wonderful people at Acronis and Workiva, who have had to listen to me drone on about this book I am writing for what feels like forever. They’ve been good sports (mostly).

    about this book

    This book builds on your existing programming skills to help you seamlessly upskill your coding practice or transition to C# from Java or another object-oriented language. You’ll learn to write the kind of idiomatic C# code that’s essential for enterprise development. This book discusses essential backend skills and puts them into practice with a common career challenge: refactoring a legacy codebase to be secure, clean, and readable. By the time you’re done, you’ll have a professional-level understanding of C# and be ready to start specializing with advanced-level resources.

    There’s no Hello, World or Computer Science 101 basics—you’ll learn by refactoring an out-of-date legacy codebase, using new techniques, tools, and best practices to bring it up to modern C# standards. Throughout this book, we take an existing codebase (written in the .NET Framework) and refactor it, with a simplified API, to .NET 5.

    Who should read this book

    If you are a developer proficient in an object-oriented programming language, be it Java, Dart, C++, or what have you, this book can help you get up to speed in C# and .NET without completely starting over. A lot of your knowledge carries over, so why learn how to write an if statement for the 500th time?

    Similarly, if you are proficient in a programming language like Go, C, JavaScript, Python, or any other mainstream language, after reading this book you can write clean, idiomatic C#. You may want to read up on some object-oriented design principles, but this should not prove to be a steep barrier to entry (if you’re coming from Go, make sure to pay extra attention whenever we use interfaces; they do not work the same).

    Lastly, if you are a developer who has been using C# for a while now and is wondering how to level-up your knowledge: this book is for you. A lot of advanced C# resources assume knowledge that is not covered in introductory or beginner resources. This book aims to bridge that gap.

    How this book is organized: A roadmap

    This book has a somewhat unconventional approach to its structure compared to a regular technical book. Most technical books are reference books or can be read in any order. This book is not a reference book, and to get the most out of it, you need to read the chapters in order. The book is structured around the following six parts, as shown in figure figure 1:

    Using C# and .NET—In chapter 1 we discuss what this book is, what it teaches, and what it does not teach. Chapter 2 is a brief tour of the C# language and .NET ecosystem, focusing on what sets .NET apart from other platforms and the C# compilation story.

    The existing codebase—In this part, I guide you through the exploration of the codebase we inherit. This part is a detailed walk-through of the existing codebase, with a discussion on potential improvements and design flaws.

    The database access layer—Following part 2, we start to rewrite the entire service. In part 3, we focus on creating a new .NET Core project and learn how we can use Entity Framework Core to connect to a cloud (or local) database. Other discussed topics include the repository/service pattern, virtual methods and properties, and sealed classes.

    The repository layer—In part 4, we step into the land of the repository/service pattern and implement five repository classes. You also learn about dependency injection, multithreading (including locking, mutexes, and semaphores), custom equality comparisons, test-driven development, generics, extension methods, and LINQ.

    The service layer—The next step is to implement the service layer classes. In part 5, we write four service layers from the ground up and talk about reflection, mocking, coupling, runtime assertions and type checks, error handling, structs, and yield return.

    The controller layer—Part 6 is the final step in our rewrite of the service we initially inherited in part 2. This part sees us writing two controller classes and has us perform acceptance testing. Besides those topics, we also broach ASP.NET Core middleware, HTTP routing, custom data binding, data serialization and deserialization, and generating an OpenAPI specification at runtime.

    A lot of chapters in this book (and some sections within chapters) have exercises designed to test your knowledge of the material. You can complete these exercises quickly. I encourage you to complete these when you encounter them and to revisit sections you may have skimmed or misunderstood.

    Figure 0.1 A flowchart of suggested routes to read this book. Follow the steps, and answer the questions to achieve your ideal reading experience. This flowchart is inspired by the book structure flowcharts in Donald Knuth’s The Art of Computer Programming series.

    About the code

    At the time of writing, the .NET landscape can be divided into three major pieces: .NET Framework 4.x, .NET Core 3.x, and.NET 5. The entire book uses .NET 5, except for chapters 3 and 4 (for reasons you will understand after reading those chapters).

    The C# language versions used are C# 3 and C# 9 (we do not use any C# 9–specific features in most of the book, so an installation of C# 8 works as well). Because C# languages are backward compatible, you just need to install the latest version (at the time of writing, either C# 8 or C# 9 preview). The chapters with provided source code are 2, 3 and 4 (combined), 5, 6, 7, 8, 9, 10, 11, 12, 13, and 14.

    To run the code, you need to install a version of .NET Framework higher than 3.5 (if you want to run the code in chapters 3 and 4) and .NET 5. If you want to run the database used in the book locally or have trouble installing anything needed in this book, you can find installation instructions in appendix C (Installation guides). This book mostly uses Visual Studio as its IDE, but you can use any IDE that supports C# (or none at all) if you please. Visual Studio 2019 has a free version called Visual Studio 2019 Community. When we encounter things that require Visual Studio, the book notes this as such. The code and .NET 5 should run on Windows, macOS, and Linux. The book uses the command line (or terminal, for you macOS users) wherever possible to avoid a reliance on any particular IDE or operating system.

    This book contains many examples of source code both in numbered listings and in-line with normal text. In both cases, source code is formatted in a fixed-width font like this to separate it from ordinary text. Sometimes code is also in bold to highlight code that has changed from previous steps in the chapter, such as when a new feature adds to an existing line of code.

    In many cases, the original source code has been reformatted; line breaks were added, and indentation was reworked to accommodate the available page space in the book. In some cases, even this was not enough, and listings include line-continuation markers (➥). Code annotations accompany many of the listings, highlighting important concepts. Also note that curly braces typically have been placed on the preceding lines for new code blocks. This is not the appropriate real-world C# convention but was done to preserve space. The source code itself does not use this convention.

    liveBook discussion forum

    Purchase of Code Like a Pro in C# includes free access to a private web forum run by Manning Publications where you can make comments about the book, ask technical questions, and receive help from the author and from other users. To access the forum, go to https://livebook.manning.com/book/code-like-a-pro-in-c-sharp/welcome/v-9/. You can also learn more about Manning’s forums and the rules of conduct at https://livebook.manning.com/#!/discussion.

    Manning’s commitment to our readers is to provide a venue where a meaningful dialogue between individual readers and between readers and the author can take place. It is not a commitment to any specific amount of participation on the part of the author, whose contribution to the forum remains voluntary (and unpaid). We suggest you try asking him some challenging questions lest his interest stray! The forum and the archives of previous discussions will be accessible from the publisher’s website as long as the book is in print.

    about the author

    Jort Rodenburg is a software engineer, author, and public speaker. He specializes in C# and has worked on software in a variety of fields, such as financial compliance and reporting, inkjet printing, medical imaging, distributed systems, and cyber security. Jort has mentored engineers proficient in a different programming language to help them get up to speed in C# and .NET. Jort also speaks on all things C#, .NET, and programming at conferences and meetups.

    about the cover illustration

    The figure on the cover of Code Like a Pro in C# is captioned Homme Samojede, or Samojede Man. The illustration is taken from a collection of dress costumes from various countries by Jacques Grasset de Saint-Sauveur (1757–1810), titled Costumes de Différents Pays, published in France in 1797. Each illustration is finely drawn and colored by hand. The rich variety of Grasset de Saint-Sauveur’s collection reminds us vividly of how culturally apart the world’s towns and regions were just 200 years ago. Isolated from each other, people spoke different dialects and languages. In the streets or in the countryside, it was easy to identify where they lived and what their trade or station in life was just by their dress.

    The way we dress has changed since then and the diversity by region, so rich at the time, has faded away. It is now hard to tell apart the inhabitants of different continents, let alone different towns, regions, or countries. Perhaps we have traded cultural diversity for a more varied personal life—certainly for a more varied and fast-paced technological life.

    At a time when it is hard to tell one computer book from another, Manning celebrates the inventiveness and initiative of the computer business with book covers based on the rich diversity of regional life of two centuries ago, brought back to life by Grasset de Saint-Sauveur’s pictures.

    Part 1 Using C# and .NET

    In this first part of the book, we’ll take a brief tour of the C# language and talk about some of its features. Chapter 1 covers what C# and .NET are and why you would (and would not) use them for your projects. Chapter 2 dives deeper into the various iterations of .NET and takes a C# method through its compilation process, stopping at each major step along the way.

    Although this part is truly the introduction of this book, it still provides invaluable information to somebody familiar with C#. Some of the knowledge introduced in these first two chapters are things you need to know before moving on to more advanced topics.

    1 Introducing C# and .NET

    This chapter covers

    Understanding what C# and .NET are

    Learning why you would use C# for your projects (and why you wouldn’t)

    Switching to C# and how to get started

    Another book on C#, you say? Yes, another one. Plenty of books are written about C# and .NET, but this book has one fundamental difference: I wrote this book to help you develop clean, idiomatic C# code in your day-to-day life. This book is not a reference book but rather a practical guide. This book does not cover things like how to write an if statement, what a method signature is, or what an object is. We are not concerned about syntax but instead focus on concepts and ideas. There is a difference between knowing the syntax of a language and being able to write clean, idiomatic code. After going through this book, that is exactly what you will be able do. Whatever your background is and whatever programming languages you know, as long as you understand object-oriented programming, this book helps you shift into the C# and .NET ecosystem, as shown in figure 1.1.

    Figure 1.1 Every chapter introduction contains a progress diagram, which allows you to quickly figure out where you are in the book.

    What do organizations like Microsoft, Google, and the US government have in common? They all use C#—and for good reason. But why? C# is just another programming language. It bears similarities to Java and C++, allows for both object-oriented and functional programming, and enjoys wide support from a large open source community. Great. Now, why should you care? In this chapter, we’ll explore that question in depth, but let me reveal a couple of spoilers: C# excels at allowing you to create scalable software. To start writing C#, all you need is the .NET SDK of your choice (more on that in chapter 2) and perhaps an IDE. The language and runtime are open source.

    Any time you look online for C#, chances are, you come across the .NET Framework. You can think about the .NET Framework as your warm blanket, a warm fire, and a mug of hot chocolate on a winter day, providing you with everything you need: libraries that encapsulate low-level Windows APIs, expose commonly used data structures and provide wrappers for complicated algorithms. Daily development in C# almost certainly involves the .NET Framework, .NET Core, or .NET 5, so we’ll explore these frameworks where appropriate.

    Figure 1.2 shows where this book’s topics fit in a general .NET web architecture. It also shows the architecture we use to completely rewrite an existing application, which we’ll start in chapter 5 (the green/dashed arrows indicate this path).

    Figure 1.2 An example of a typical web service architecture on a Microsoft stack. This book follows the approach shown by the green/dashed arrows. This book covers the presentation, business logic, and data access layers.

    For those of you with prior experience in C#: this book sits between beginner and advanced resources. With the skills taught in this book, you can bridge the knowledge gap and prepare yourself for advanced skills. The first two chapters may seem a bit basic to you, but I invite you to not skim over these. It is always good to refresh your knowledge.

    1.1 Why work in C#?

    If you are already familiar with a programming language other than C# and like using it, why should you use C#? Perhaps you were hired by a company that uses only C#. Or maybe you just want to see what all the fuss is about.

    I promise not to repeatedly tell you that C# is a strongly typed object-oriented programming language that enables cross-platform development of scalable enterprise software. You are likely aware of that, and it is hardly the most exciting sentence to dissect. In this section, we cover the buzzwords in that definition once and do not touch on it again. At the risk of sounding like I’m employed by Microsoft’s marketing department, for the rest of this section, we’ll focus on the following highlights and use cases of C#:

    C# (and the .NET ecosystem) enables the development of software in an economical way. Economical solutions are important because enterprise development is the bread and butter of C#.

    C# can improve code stability and is maintainable because of its support for self-documenting code, secure libraries, and ease of use.

    C# is developer friendly and easy to use. There’s nothing worse than discovering that the programming language you want to use does not have good support for the things you love (such as a stable package manager, good support for unit testing, and a cross-platform runtime).

    Of course, writing scalable, maintainable, and developer-friendly clean code can be done in most (if not all) programming languages. The difference lies in the developer experience. Some languages are really good at guiding you in writing clean code, whereas others are not. C# is not perfect, but it does try to help you in this regard.

    1.1.1 Reason 1: C# is economical

    C# is free to use and develop in. The language and platform are fully open source, all documentation is free, and most tooling has free options. For example, a common C# setup includes an installation of C# 8, .NET 5, and Visual Studio Community. All these are free and used in this book. No license fee is required for the runtime, and you can deploy the end product wherever you want.

    1.1.2 Reason 2: C# is maintainable

    When we talk about maintainability in this book, we mean the ability to fix bugs, change functionality, and address other issues without unintended side effects. This sounds like an obvious requirement for any programming language, but it is very hard to implement. C# has features that improve the maintainability (and, therefore, safe extensibility) of large codebases. Think, for example, about generics and Language-Integrated Query (LINQ). We’ll discuss these two things throughout the book, but they are examples of the platform exposing functionalities that can help you write better code.

    For a company, maintainability might not be the number one priority on the surface, but if you develop code that is maintainable (meaning clean code that is easily extendable and backed by tests), development costs drop. Development costs dropping when writing maintainable code may seem counterintuitive at first: maintainable code takes longer to write and architect, driving up the initial costs of development. However, imagine what happens after a little while when a user discovers a bug or they want an additional feature. If we write maintainable code, we can quickly and easily find the bug (and fix it). Adding the feature is simpler because the codebase is extensible. If we can easily extend and fix a codebase, development costs go down.

    1.1.3 Reason 3: C# is developer friendly and easy to use

    Enterprise development is the bread and butter of C# development and where C# and .NET shine. What would your ideal codebase look like in an enterprise environment? Perhaps you would like a codebase that is easily navigable with a solid package manager and backed by tests (unit, integration, and smoke). Let’s also throw in excellent documentation and cross-platform support.

    DEFINITION Self-documenting code means code that is written clearly enough that we need no comments to explain the logic. The code documents itself. For example, if you have a method called DownloadDocument, others can have some inkling of what it does. There is no need to add a comment saying that the logic inside the method downloads a document.

    To top things off, perhaps we can have good integration with a cloud service for continuous integration and delivery (CI/CD). A pragmatic view tells us that the likelihood of you having such a codebase is not very high. Of course, this wish list is unrealistic for most scenarios. However, if you want to do some of these things (or all of them, if you are adventurous), C# does not work against you. It offers existing workflows, functionalities, and native libraries to get you 99% of the way there.

    Developers coming from a language such as Java should see some similarities in the project structure. Although some differences exist, they are not large. We’ll discuss the C# project structure in depth throughout the book.

    .NET also has support for several popular testing frameworks. Microsoft provides the Visual Studio Unit Testing Framework, which contains (and by extension is sometimes called) MSTest. MSTest is just the command-line runner for the Visual Studio Unit Testing Framework. Other commonly used testing frameworks are xUnit and NUnit. You can also find support for mocking frameworks such as Moq (Moq is similar to Java’s Mockito or Go’s GoMock. We’ll learn more about using Moq with unit tests in section 10.3.3.), SpecFlow (behavior-driven development similar to Cucumber), NFluent (a fluent assertion library), FitNesse, and many more.

    Last, you can run C# on a host of platforms, albeit with some limitations (some older platforms are restricted to older versions of C# and the .NET Framework). With .NET 5, you can run the same code on Windows 10, Linux, and macOS. This functionality got its start as .NET Core, a spinoff of the .NET Framework that has since merged with .NET Framework (and other frameworks) to create .NET 5. You can even run C# code on iOS and Android through Xamarin and on PlayStation, Xbox, and Nintendo Switch platforms through Mono.

    1.2 Why not work in C#?

    C# isn’t the best choice for everybody under every circumstance. It is imperative that you choose the best tool for the job. C# works well in a wide variety of situations, but a few use cases you might not want to use C# and .NET for follow:

    Operating system development

    Real-time operating system–driven code (embedded development)

    Numerical computing

    Let’s examine briefly why C# might not be an ideal fit for these use cases.

    1.2.1 Operating system development

    Operating system (OS) development is an incredibly important corner of software engineering, yet not many people develop OSes. Developing an OS takes a lot of time and commitment, with codebases routinely going into millions of lines of code, developed and maintained over many years and sometimes decades.

    The main reason C# is not suitable for OS development comes down to spotty support for manual memory management (unmanaged code) and C#’s compilation process. Although C# allows the use of pointers when using unsafe mode, it does not rival a programming language like C in ease of use for manual memory management.

    Another problem with using C# to develop an OS is its partial reliance on a just-in-time (JIT) compiler (more on this in chapter 2). Imagine having to run your operating system through a virtual machine. Performance would be a problem because the virtual machine has to play catch-up all the time to run the JIT-compiled code, which is similar to what happens when .NET code runs on your machine. This critique means that a fully statically compiled language is a better fit for OS development.

    Yet, examples of OSes developed in higher-level languages do exist. For example, Pilot-OS (created by Xerox PARC in 1977) was written in Mesa,¹ a predecessor of Java.

    If you want to learn more about operating system development, the wiki for the osdev.org community is an excellent resource (wiki.osdev.org). There you can find guides to get started, tutorials, and reading suggestions. Resources for learning C include Jens Gustedt’s Modern C (Manning, 2019) and the classic book, The C Programming Language, by Brian Kernighan and Dennis Ritchie (Prentice Hall, 1988).

    1.2.2 Real-time operating

    Enjoying the preview?
    Page 1 of 1