Code like a Pro in C#
()
About this ebook
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
Related to Code like a Pro in C#
Related ebooks
Functional Programming in C#, Second Edition Rating: 0 out of 5 stars0 ratingsLearning ASP.NET Core MVC Programming Rating: 5 out of 5 stars5/5Microservices in .NET, Second Edition Rating: 0 out of 5 stars0 ratingsC# Programming Illustrated Guide For Beginners & Intermediates: The Future Is Here! Learning By Doing Approach Rating: 0 out of 5 stars0 ratingsBDD in Action: Behavior-Driven Development for the whole software lifecycle Rating: 0 out of 5 stars0 ratingsGrokking Simplicity: Taming complex software with functional thinking Rating: 4 out of 5 stars4/5Effective Software Testing: A developer's guide Rating: 0 out of 5 stars0 ratingsC# Programming & Software Development: 6 In 1 Coding Syntax, Expressions, Interfaces, Generics And App Debugging Rating: 0 out of 5 stars0 ratingsSoftware Mistakes and Tradeoffs: How to make good programming decisions Rating: 0 out of 5 stars0 ratingsC# in Depth Rating: 5 out of 5 stars5/5ASP.NET Core in Action, Second Edition Rating: 0 out of 5 stars0 ratingsEntity Framework Core in Action, Second Edition Rating: 0 out of 5 stars0 ratings.NET Design Patterns Rating: 3 out of 5 stars3/5Dependency Injection Principles, Practices, and Patterns Rating: 5 out of 5 stars5/5Functional C# Rating: 5 out of 5 stars5/5Hands-On Network Programming with C# and .NET Core: Build robust network applications with C# and .NET Core Rating: 0 out of 5 stars0 ratingsC# 7 and .NET Core: Modern Cross-Platform Development - Second Edition Rating: 5 out of 5 stars5/5Mastering C# and .NET Framework Rating: 5 out of 5 stars5/5Unit Testing Principles, Practices, and Patterns Rating: 4 out of 5 stars4/5C# 7 and .NET Core Cookbook Rating: 0 out of 5 stars0 ratingsEntity Framework Core Cookbook - Second Edition Rating: 0 out of 5 stars0 ratings.NET Core in Action Rating: 0 out of 5 stars0 ratingsBlazor in Action Rating: 0 out of 5 stars0 ratingsFunctional Programming in C#: How to write better C# code Rating: 5 out of 5 stars5/5PROGRAMMING IN C# 10 - Basic Techniques Rating: 2 out of 5 stars2/5C# Programming Cookbook Rating: 0 out of 5 stars0 ratingsWriting High-Performance .NET Code, 2nd Edition Rating: 5 out of 5 stars5/5The Art of Unit Testing: with examples in C# Rating: 4 out of 5 stars4/5Multithreading in C# 5.0 Cookbook Rating: 0 out of 5 stars0 ratings
Programming For You
Python Programming : How to Code Python Fast In Just 24 Hours With 7 Simple Steps Rating: 4 out of 5 stars4/5Excel 101: A Beginner's & Intermediate's Guide for Mastering the Quintessence of Microsoft Excel (2010-2019 & 365) in no time! Rating: 0 out of 5 stars0 ratingsExcel : The Ultimate Comprehensive Step-By-Step Guide to the Basics of Excel Programming: 1 Rating: 5 out of 5 stars5/5Coding All-in-One For Dummies Rating: 4 out of 5 stars4/5HTML in 30 Pages Rating: 5 out of 5 stars5/5Learn PowerShell in a Month of Lunches, Fourth Edition: Covers Windows, Linux, and macOS Rating: 5 out of 5 stars5/5Learn to Code. Get a Job. The Ultimate Guide to Learning and Getting Hired as a Developer. Rating: 5 out of 5 stars5/5Python: For Beginners A Crash Course Guide To Learn Python in 1 Week Rating: 4 out of 5 stars4/5Spies, Lies, and Algorithms: The History and Future of American Intelligence Rating: 4 out of 5 stars4/5Linux: Learn in 24 Hours Rating: 5 out of 5 stars5/5SQL QuickStart Guide: The Simplified Beginner's Guide to Managing, Analyzing, and Manipulating Data With SQL Rating: 4 out of 5 stars4/5Grokking Algorithms: An illustrated guide for programmers and other curious people Rating: 4 out of 5 stars4/5Tiny Python Projects: Learn coding and testing with puzzles and games Rating: 4 out of 5 stars4/5Python QuickStart Guide: The Simplified Beginner's Guide to Python Programming Using Hands-On Projects and Real-World Applications Rating: 0 out of 5 stars0 ratingsC# Programming from Zero to Proficiency (Beginner): C# from Zero to Proficiency, #2 Rating: 0 out of 5 stars0 ratingsHTML & CSS: Learn the Fundaments in 7 Days Rating: 4 out of 5 stars4/5SQL: For Beginners: Your Guide To Easily Learn SQL Programming in 7 Days Rating: 5 out of 5 stars5/5SQL All-in-One For Dummies Rating: 3 out of 5 stars3/5C# 7.0 All-in-One For Dummies Rating: 0 out of 5 stars0 ratingsiPhone For Dummies Rating: 0 out of 5 stars0 ratingsJavaScript All-in-One For Dummies Rating: 5 out of 5 stars5/5C All-in-One Desk Reference For Dummies Rating: 5 out of 5 stars5/5
Reviews for Code like a Pro in C#
0 ratings0 reviews
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
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).