Understanding C# basics
To learn C#, you will need to create some simple applications. To avoid overloading you with too much information too soon, the chapters in the first part of this book will use the simplest type of application: a console application.
Let's start by looking at the basics of the grammar and vocabulary of C#. Throughout this chapter, you will create multiple console applications, with each one showing a feature of the C# language. We will start by creating a console app that shows the compiler version.
- If you've completed Chapter 1, Hello, C#! Welcome, .NET!, then you will already have a
Code
folder in your user folder. If not, then you'll need to create it. - Create a subfolder named
Chapter02
, with a sub-folder namedBasics
. - Start Visual Studio Code and open the
Chapter02/Basics
folder. - In Visual Studio Code, navigate to View | Terminal, and enter the following command:
dotnet new console
- In EXPLORER, click the
Program.cs
file, and then click on Yes to add the missing required assets. - Open the
Program.cs
file, and at the top of the file, under theusing
statement, add a statement to show the current C# version as an error, as shown in the following code:#error version
- Navigate to View | Problems, and note the compiler version and language version appear as a compiler error message number CS8304, as shown in the following screenshot:
Figure 2.1: A compiler error that shows the C# language version
- Comment out the statement that causes the error, as shown in the following code:
// #error version
Understanding C# grammar
The grammar of C# includes statements and blocks. To document your code, you can use comments.
Good Practice: Comments should never be the only way that you document your code. Choosing sensible names for variables and functions, writing unit tests, and creating literal documents are other ways to document your code.
Statements
In English, we indicate the end of a sentence with a full stop. A sentence can be composed of multiple words and phrases, with the order of words being part of the grammar. For example, in English, we say "the black cat."
The adjective, black, comes before the noun, cat. Whereas French grammar has a different order; the adjective comes after the noun: "le chat noir." What's important to take away from this is that the order matters.
C# indicates the end of a statement with a semicolon. A statement can be composed of multiple variables and expressions. For example, in the following statement, totalPrice
is a variable and subtotal + salesTax
is an expression:
var totalPrice = subtotal + salesTax;
The expression is made up of an operand named subtotal
, an operator +
, and another operand named salesTax
. The order of operands and operators matters.
Comments
When writing your code, you're able to add comments to explain your code using a double slash, //
. By inserting //
the compiler will ignore everything after the //
until the end of the line, as shown in the following code:
// sales tax must be added to the subtotal
var totalPrice = subtotal + salesTax;
Visual Studio Code will add or remove the comment double slashes at the start of the currently selected line(s) if you press Ctrl + K + C to add them or Ctrl + K + U to remove them. In macOS, press Cmd instead of Ctrl.
To write a multiline comment, use /*
at the beginning and */
at the end of the comment, as shown in the following code:
/*
This is a multi-line
comment.
*/
Blocks
In English, we indicate a new paragraph by starting a new line. C# indicates a block of code with the use of curly brackets, { }
. Blocks start with a declaration to indicate what is being defined. For example, a block can define a namespace, class, method, or a statement, something we will learn more about later.
In your current project, note that the grammar of C# is written for you by the dotnet
CLI tool. I've added some comments to the statements written by the project template, as shown in the following code:
using System; // a semicolon indicates the end of a statement
namespace Basics
{ // an open brace indicates the start of a block
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!"); // a statement
}
}
} // a close brace indicates the end of a block
Understanding C# vocabulary
The C# vocabulary is made up of keywords, symbol characters, and types.
Some of the predefined, reserved keywords that you will see in this book include using
, namespace
, class
, static
, int
, string
, double
, bool
, if
, switch
, break
, while
, do
, for
, and foreach
.
Some of the symbol characters that you will see include "
, '
, +
, -
, *
, /
, %
, @
, and $
.
Changing the color scheme for syntax
By default, Visual Studio Code shows C# keywords in blue in order to make them easier to differentiate from other code. Visual Studio Code allows you to customize the color scheme:
- In Visual Studio Code, navigate to Code | Preferences | Color Theme (it is on the File menu on Windows), or press Ctrl or Cmd + K, Ctrl or Cmd + T.
- Select a color theme. For reference, I'll use the Light+ (default light) color theme so that the screenshots look good in a printed book.
There are other contextual keywords that only have a special meaning in a specific context. However, that still means that there are only about 100 actual C# keywords in the language.
Comparing programming languages to human languages
The English language has more than 250,000 distinct words, so how does C# get away with only having about 100 keywords? Moreover, why is C# so difficult to learn if it has only 0.0416% of the number of words in the English language?
One of the key differences between a human language and a programming language is that developers need to be able to define the new "words" with new meanings. Apart from the 104 keywords in the C# language, this book will teach you about some of the hundreds of thousands of "words" that other developers have defined, but you will also learn how to define your own "words."
More Information: Programmers all over the world must learn English because most programming languages use English words such as namespace and class. There are programming languages that use other human languages, such as Arabic, but they are rare. If you are interested in learning, this YouTube video shows a demonstration of an Arabic programming language: https://youtu.be/dkO8cdwf6v8
Help for writing correct code
Plain text editors such as Notepad don't help you write correct English. Likewise, Notepad won't help you write correct C# either.
Microsoft Word can help you write English by highlighting spelling mistakes with red squiggles, with Word saying that "icecream" should be ice-cream or ice cream, and grammatical errors with blue squiggles, such as a sentence should have an uppercase first letter.
Similarly, Visual Studio Code's C# extension helps you write C# code by highlighting spelling mistakes, such as the method name should be WriteLine
with an uppercase L
, and grammatical errors, such as statements that must end with a semicolon.
The C# extension constantly watches what you type and gives you feedback by highlighting problems with colored squiggly lines, similar to that of Microsoft Word.
Let's see it in action:
- In
Program.cs
, change theL
in theWriteLine
method to lowercase. - Delete the semicolon at the end of the statement.
- Navigate to View | Problems, or press Ctrl or Cmd + Shift + M, and note that a red squiggle appears under the code mistakes and details are shown in the PROBLEMS window, as you can see in the following screenshot:
Figure 2.2: The PROBLEMS window showing two compile errors
- Fix the two coding mistakes.
Verbs are methods
In English, verbs are doing or action words, like run and jump. In C#, doing or action words are called methods. There are hundreds of thousands of methods available to C#. In English, verbs change how they are written based on when in time the action happens. For example, Amir was jumping in the past, Beth jumps in the present, they jumped in the past, and Charlie will jump in the future.
In C#, methods such as WriteLine
change how they are called or executed based on the specifics of the action. This is called overloading, which is something we will cover in more detail in Chapter 5, Building Your Own Types with Object-Oriented Programming. But for now, consider the following example:
// outputs a carriage-return
Console.WriteLine();
// outputs the greeting and a carriage-return
Console.WriteLine("Hello Ahmed");
// outputs a formatted number and date and a carriage-return
Console.WriteLine(
"Temperature on {0:D} is {1}°C.", DateTime.Today, 23.4);
A different analogy is that some words are spelled the same, but have different meanings depending on the context.
Nouns are types, fields, and variables
In English, nouns are names that refer to things. For example, Fido is the name of a dog. The word "dog" tells us the type of thing that Fido is, and so in order for Fido to fetch a ball, we would use his name.
In C#, their equivalents are types, fields, and variables. For example, Animal
and Car
are types; that is, they are nouns for categorizing things. Head
and Engine
are fields, that is, nouns that belong to Animal
and Car
. While Fido
and Bob
are variables, that is, nouns for referring to a specific thing.
There are tens of thousands of types available to C#, though have you noticed how I didn't say, "There are tens of thousands of types in C#?" The difference is subtle but important. The language of C# only has a few keywords for types, such as string
and int
, and strictly speaking, C# doesn't define any types. Keywords such as string
that look like types are aliases, which represent types provided by the platform on which C# runs.
It's important to know that C# cannot exist alone; after all, it's a language that runs on variants of .NET. In theory, someone could write a compiler for C# that uses a different platform, with different underlying types. In practice, the platform for C# is .NET, which provides tens of thousands of types to C#, including System.Int32
, which is the C# keyword alias int
maps to, as well as many more complex types, such as System.Xml.Linq.XDocument
.
It's worth taking note that the term type is often confused with class. Have you ever played the parlor game Twenty Questions, also known as Animal, Vegetable, or Mineral? In the game, everything can be categorized as an animal, vegetable, or mineral. In C#, every type can be categorized as a class
, struct
, enum
, interface
, or delegate
. The C# keyword string
is a class
, but int
is a struct
. So, it is best to use the term type to refer to both.
Revealing the extent of the C# vocabulary
We know that there are more than 100 keywords in C#, but how many types are there? Let's now write some code to find out how many types (and their methods) are available to C# in our simple console application.
Don't worry about how this code works for now; it uses a technique called reflection:
- We'll start by adding the following statements at the top of the
Program.cs
file:using System.Linq; using System.Reflection;
- Inside the
Main
method, delete the statement that writesHello World!
and replace it with the following code:// loop through the assemblies that this app references foreach (var r in Assembly.GetEntryAssembly() .GetReferencedAssemblies()) { // load the assembly so we can read its details var a = Assembly.Load(new AssemblyName(r.FullName)); // declare a variable to count the number of methods int methodCount = 0; // loop through all the types in the assembly foreach (var t in a.DefinedTypes) { // add up the counts of methods methodCount += t.GetMethods().Count(); } // output the count of types and their methods Console.WriteLine( "{0:N0} types with {1:N0} methods in {2} assembly.", arg0: a.DefinedTypes.Count(), arg1: methodCount, arg2: r.Name); }
- Navigate to View | Terminal.
- In TERMINAL, enter the following command:
dotnet run
- After running that command, you will see the actual number of types and methods that are available to you in the simplest application when running on your OS. The numbers of types and methods displayed will be different depending on the operating system that you are using, as shown in the following outputs:
// Output on Windows 0 types with 0 methods in System.Runtime assembly. 103 types with 1,094 methods in System.Linq assembly. 46 types with 662 methods in System.Console assembly. // Output on macOS 0 types with 0 methods in System.Runtime assembly. 103 types with 1,094 methods in System.Linq assembly. 57 types with 701 methods in System.Console assembly.
- Add statements to the top of the
Main
method to declare some variables, as shown highlighted in the following code:static void Main(string[] args) { // declare some unused variables using types // in additional assemblies System.Data.DataSet ds; System.Net.Http.HttpClient client;
By declaring variables that use types in other assemblies, those assemblies are loaded with our application, which allows our code to see all the types and methods in them. The compiler will warn you that you have unused variables but that won't stop your code from running.
- Run the console application again and view the results, which should look similar to the following outputs:
// Output on Windows 0 types with 0 methods in System.Runtime assembly. 376 types with 6,763 methods in System.Data.Common assembly. 533 types with 5,193 methods in System.Net.Http assembly. 103 types with 1,094 methods in System.Linq assembly. 46 types with 662 methods in System.Console assembly. // Output on macOS 0 types with 0 methods in System.Runtime assembly. 376 types with 6,763 methods in System.Data.Common assembly. 522 types with 5,141 methods in System.Net.Http assembly. 103 types with 1,094 methods in System.Linq assembly. 57 types with 701 methods in System.Console assembly.
Now, you have a better sense of why learning C# is a challenge, because there are so many types and methods to learn. Methods are only one category of a member that a type can have, and other programmers are constantly defining new members!