Introduction to C#
C# is a modern, object-oriented, component-oriented and type-safe programming language developed by Microsoft. It has its roots in the C family of languages, making it loosely similar to C++, Java or JavaScript. C# programs run on .NET, a virtual execution system called the common language runtime (CLR) and a set of class libraries.
Two techniques for displaying literal-string data to the console.
Console.WriteLine("Hello "); // WriteLine appends a new line after printing the output to the console
Console.WriteLine("World!");
// Hello
// World!
Console.Write("Hello World!");
Console.Write(" ");
Console.Write("This will print on the same line.");
// Hello World! This will print on the same line.
In these simple blocks of code:
- → Console is a class
- → Write and WriteLine are methods. Methods are always followed by "()"- fancy term: method invocation operator. Each method has only one job.
- → Hello World! is a literal string
- → The period is the member access operator used to navigate from a class to its methods
- → the semicolon is the end of statement operator and it indicates the end of a command
Command-Line Interface
The structure of a CLI command consists of three parts:
- the driver: dotnet
- the command: new (new application) console (type of application)
- the command arguments: -o ./new_project_folder_name
This command will use a .NET program template to create a new console application in the specified folder location:
dotnet new console -o ./new_project_folder_name
To compile a build of your application, use the following command inside of your project directory:
dotnet build
This command will build the project and its dependencies into a set of binaries.
To run/execute your application, enter the following command:
dotnet run
Data types
Literal String
Console.WriteLine("Hello :)");
// Hello! :)
Members of string Type:
int howLong = myString.Length;
string upper = myString.ToUpper();
string lower = myString.ToLower();
bool hasHello = myString.Contains("Hello");
string replace = myString.Replace("a", "b");
string substring = myString.Substring(1, 3); // first number: where to start from, second number: how many characters
bool firstName = myString.Equals("Lena");
Char Literal
A char literal is a single alphanumeric character surrounded by single quotes that we can use for presentation - not calculation.
Console.WriteLine('A');
// A
Members of char Type:
char myChar = 'a';
bool isCharWhiteSpace = char.IsWhiteSpace(myChar); // checking if myChar is an empty space
bool isCharDigit = char.IsDigit(myChar); // checking if myChar is a digit
bool isCharPunctuation = char.IsPunctuation(myChar); // checking if myChar is a punctuation mark
Integer literal
To display a whole number value in the console we use int literals.
Console.WriteLine(123)
// 123
Members of int Type:
int MaxValue = int.MaxValue; // 2147483647
int MinValue = int.MinValue; // -2147483648
Floating-point Literal
C# supports three data types to represent decimal numbers: float, double, and decimal. Each type supports varying degrees of precision.
To create a float, we append the letter F/f (literal suffix) after the number. The literal suffix tells the compiler you wish to work with a value of float type.
Console.WriteLine(0.25F)
// 0.25
Double literal
To create a double literal, we enter a decimal number. The compiler defaults to a double literal when a decimal number is entered without a literal suffix.
Console.WriteLine(2.625)
// 2.625
Decimal literal
To create a decimal literal, append the literal suffix m/M after the number. This will tell the compiler that we will be working with decimal values.
Console.WriteLine(12.39816m)
// 12.39816
Boolean literals
We use a bool literal to print a value representing true or false.
Console.WriteLine(true)
// True
Declaring variables
Variables are temporary storage containers for data. They can only hold values matching its specified data types.
To create a new variable we need to declare its data type followed by its name. Then we can assign a value to that variable using the equals sign. The assignment happens from right to left.
string myName;
myName = "Lena";
int myAge = 99;
Implicitly typed local variables
The var keyword tells the C# compiler that the data type is implied by the assigned value. Once the type is implied, the variable cannot be reassigned to a different data type.
Variables using the var keyword must be initialized.
var myAge = 99;
Byte(sbyte) and Short(ushort)
Boolean literals
Working with string literals
Character escape sequences
In C#, the escape character sequence begins with a backslash "\" followed by the character you're escaping, for example \n for a new line, \t for tab, or \" to print the quotation mark.
Console.WriteLine("Hello\nWorld!");
// Hello
World!
To print a single backslash, use \\.
Console.WriteLine("c:\\source\\repos");
// c:\source\repos
Verbatim string literal
To keep all whitespace and characters without the need to escape the backslash, we can use @.
Console.WriteLine(@"c:\source\repos
- we're keeping the white space");
// c:\source\repos
- we're keeping the white space
Unicode escape characters
We can use the \u escape sequence, then a four-character code representing some character in Unicode (UTF-16).
Console.WriteLine("\u3053\u3093\u306B\u3061\u306F World!");
// こんにちは World! (Kon'nichiwa World!)
Comparing strings
We can compare strings using Equals() method, but it's a case-sensitive
method.
Here's a trick to compare strings regardless of letter-casing.
bool sameStrings = firstString.ToUpper() == anotherString.ToUpper();
String concatenation
To concatenate two strings together, you use the string concatenation operator, which is the plus symbol +.
string myName = "Lena";
string sayHello = "Hello";
Console.WriteLine(sayHello + " " + myName);
// Hello Lena
OR:
string string3 = String.Format("This is a greeting for {1}: {0}, {1}!", sayHello, myName);
Console.WriteLine(string3);
// This is a greeting for Lena: Hello, Lena!
OR:
string myName = "Lena";
string sayHello = "Hello "; // notice the space added after Hello
Console.WriteLine(String.Concat(sayHello + " " + myName));
// Hello Lena
String interpolation
String interpolation combines multiple values into a single literal string using $ and { }. This is how the string literal becomes a template.
string myName = "Lena";
string sayHello = "Hello";
string greeting = $"{sayHello} {myName}";
Console.WriteLine(greeting);
// Hello Lena
StringBuilder Type
StringBuilder doesn't create a new copy of a string every time, but changes the original one. It has quite a few methods to work with strings.
StringBuilder string1 = new StringBuilder();
string1.Append("To-Do List: "); // on the same line
string1.AppendLine("Read a chapter."); // adds a new line after
string1.AppendLine("Do shopping.");
Console.WriteLine(string1.ToString());
Converting between data types
There are three ways if converting data types: implicit conversion, explitic conversion, helpers.
Implicit conversion:
int a = 123541;
long l = a;
Explicit conversion:
double d = 123456789.0;
int a = (int) d;
// because double contains more information than int,
and some part of the data will get lost in the conversion,
we need to explicitly confirm the output data type
Working with numeric values
Add two numeric values
int firstNumber = 3;
int secondNumber = 14;
Console.WriteLine(firstNumber + secondNumber);
// 17
If we use the + symbol with both string and integer values, it will carry out concatenation.
We can use parentheses to clarify our intention of adding to the compiler, as any operations that happen inside of parentheses are always resolved first. Since both our variables are integers, the plus symbol will add both numbers together - NOT concatenate them.
int firstNumber = 3;
int secondNumber = 14;
Console.WriteLine(firstNumber + " is smaller than " + secondNumber + ". ");
Console.WriteLine(firstNumber + secondNumber);
// 3 is smaller than 14.
17
Math operations
We use: + for addition, - for subtraction, * for multiplication, / for division.
int sum = 7 + 5;
int difference = 7 - 5;
int product = 7 * 5;
int quotient = 7 / 5;
Console.WriteLine("Sum: " + sum);
Console.WriteLine("Difference: " + difference);
Console.WriteLine("Product: " + product);
Console.WriteLine("Quotient: " + quotient);
// Sum: 12
Difference: 2
Product: 35
Quotient: 1 (int cannot contain values after the decimal)
Perform division using literal decimal data
To get the correct result, we need to use a data type that supports fractional digits after the decimal point like decimal. For this to work, the quotient and at least one of numbers being divided must be of type decimal.
decimal decimalQuotient = 7 / 5.0m;
OR
decimal decimalQuotient = 7.0m / 5.0m;
NOT decimal decimalQuotient = 7 / 5;
Console.WriteLine(decimalQuotient);
// 1.4
Modulus
The modulus operator % gives us the remainder of int division. We can use it with $ and { }.
Console.WriteLine($"Modulus of 200 / 5 is {200 % 5}");
Console.WriteLine($"Modulus of 7 / 5 is {7 % 5}");
// Modulus of 200 / 5 is 0
Modulus of 7 / 5 is 2
Compound assignment operators
This addition assignment operator += adds and assigns the value on the right of the operator to the value on the left of the operator
int value = 0; // value is now 0.
value = value + 5; // value is now 5.
value += 5; // value is now 10.
value -= 4; // value is now 6.
The ++ operator increments the value of the variable by 1.
int value = 3; // value is now 0.
value = value + 1; // value is now 4.
value++; // value is now 5.
value--; // value is now 4.
If we use the operator ++ before the value (++value), the increment will happen before the value is retrieved. Likewise, value++ will increment the value after the value has been retrieved.
Working with Date and Time
C# has two built-in data types to work with time and dates: DateTime and TimeSpan.
This is a few examples of how to use them:
DateTime myBirthDayIn2024 = new DateTime(2024, 06, 01); //01 / 06 / 2024 00:00:00
DateTime myBirthDayIn2025 = myBirthDayIn2024.AddYears(1); //01 / 06 / 2025 00:00:00
DateTime startTime = DateTime.Now; //10/02/2024 21:56:25
TimeSpan workTime = new TimeSpan(8, 0, 0);
DateTime endTime = startTime.Add(workTime); //11/02/2024 05:56:25
Console.WriteLine(startTime.ToLongDateString()); //10 February 2024
Console.WriteLine(endTime.ToShortTimeString()); //05:56
If, else, else if
The curly braces can be omitted if there is only a single statement following if.
Console example:
Console.WriteLine("Enter a first number:");
string stringValue1 = Console.ReadLine();
Console.WriteLine("Enter a second number:");
string stringValue2 = Console.ReadLine();
int intValue1 = int.Parse(stringValue1);
int intValue2 = int.Parse(stringValue2);
if (intValue1 == intValue2)
{
Console.WriteLine("The values are equal!");
}
else if (intValue1 < intValue2)
{
Console.WriteLine("The first value is smaller!");
}
else
{
Console.WriteLine("The second value is smaller!");
}
Switch
The switch statement will not work with float and double.
Care labels use a pattern: constant or relational.
Each case must be unique.
The first true statement will get executed.
Console.WriteLine("Enter your age:");
int age = int.Parse(Console.ReadLine());
switch (age)
{
case < 13:
Console.WriteLine("You're a child.");
break;
case > 12: // two cases can share the same code
case < 18:
Console.WriteLine("You're a teenager.");
break;
case 25:
Console.WriteLine("You're exactly 25 years old.");
break;
case > 65:
Console.WriteLine("I'd never call you old, but we're all know that you're EXTREMELY mature. :)");
break;
case:
Console.WriteLine("You're an adult.");
break;
}
Loop options
While statement
Console.WriteLine("Enter a number: ");
int startNumber = int.Parse(Console.ReadLine());
int maxNumber = 5;
while (startNumber <= maxNumber)
{
Console.WriteLine(startNumber);
startNumber++;
}
// (if we enter 1)
1
2
3
4
5
For loop
For loops use keywords continue and break. If put after a statement, the loop will either execute a statement at a particular point, or stop the loop once that point is met.
Structure:
for (initialization; Boolean; iterator)
{
statements
}
Example:
int sum = 0;
for (int i = 0; i < 10; i++)
{
sum = sum + i;
}
Console.WriteLine(sum);
Passing variables by reference
There are two kinds of types in C#: reference types (classes, interfaces and delegates) and value types (enumerations and structs). A variable of a reference type contains a reference to its data. A variable of a value type contains its data directly. Operations on one variable can affect the object referenced by the other variable. (source: https://learn.microsoft.com/)
The ref keyword requires the variable to be
initialized before entering the method. Without ref any changes to the variable made inside
of the method will not change the variable itself.
In simple words: if arguments passed to a method are preceded by ref, they can be changed by this method.
The out keyword requires the variable to be initialized inside of the method. Apart from this detail, the out keyword behaves just like ref.
static void Main(string[] args)
{
int add;
int mult;
AddAndMultiply(3, 4, out add, out multiply);
Console.WriteLine(add); //7
Console.WriteLine(multiply); //12
}
public static void AddAndMultiply(int a, int b, out int added, out int multiplied)
{
added = a + b;
multiplied = a * b;
}
Methods
Structure:
access modifier return type MethodName (Parameters)
{
statements
}
A few things to know about methods in C#:
If the return type of a method is specified, the method MUST return a value of that type. A method that doesn't return anything is of type void.
Method overload happens when we use the same function multiple times. This is possible if the functions take different parameters or return different data types.
The order of a method's parameters is not always important, as we name our parameters when calling a method.
Method(b: 3, a: 1);
We can give a method default parameters, which do not to be listed when calling this method:
public static int AddNumbers (int a, int b, int c = 4);
Explore .NET Class Library
.NET Class Library is a prewritten collection of coding resources (classes with methods) that we can use to build our applications.
The format of calling methods of a class in the .NET Class Library is: ClassName.MethodName(),
Stateful vs stateless methods
The term state is used to describe the condition of the execution environment at a specific moment in time.
Stateless/static methods work without changing any values stored in memory. The example would be Console.WriteLine() as it doesn't impact the state of the application in any way or relies on any stored values.
When calling a stateless method, there is no need to create a new instance of its class first.
Stateful/instance methods rely on values stored in memory by previous lines of code that have already been executed. They can modify the state of the application by updating values or storing new values in memory. They keep track of their state in variables defined on the class.
When calling a stateful method, we need to create an instance of the class, and access the method on the object.
A single class can support both stateful and stateless methods. However, when you need to call stateful methods, you must first create an instance of the class so that the method can access state.
Classes
Class structure:
public class ClassName // access modifier, class definition
{ // class body
public int num1; // fields: class level variables
public string string1;
public void Method() // methods
{
Console.WriteLine("Hello!");
}
}
Class may also contain events and properties.
Classes are a reference type.
Access modifiers
public: accessible from outside
private: only accessible from within the class
protected: only accessible from within the class and its inheriters
internal:
Example:
internal class Employee
{
public string firstName;
public string lastName;
public string email;
public int numberofHoursWorked;
public double wage;
public double hourlyRate;
const int minHoursWorked = 1;
public DateTime birthDay;
public void PerformWork()
{
PerformWork(minHoursWorked);
//numberofHoursWorked++;
//Console.WriteLine($"{firstName} {lastName} has worked for {numberofHoursWorked}.");
}
public void PerformWork(int numberofHours)
{
numberofHoursWorked += numberofHours;
Console.WriteLine($"{firstName} {lastName} has worked for {numberofHours}.");
}
public double ReceiveWage(bool resetHours = true)
{
wage = numberofHoursWorked * hourlyRate;
Console.WriteLine($"{firstName} {lastName} has received £{wage} for {numberofHoursWorked} hours.");
if (resetHours)
{
numberofHoursWorked = 0;
}
return wage;
}
public void DisplayEmployeeDetails()
{
Console.WriteLine($"First name: \t{firstName} \nLast name: \t{lastName} has received £{wage} for {numberofHoursWorked} hours.");
}
}
Constructor
When we instantiate an object a constructor
method is called.
Constructors can be custom or deafult - a default one will be called if a constractor is
not specified. However, once we create a custom constructos, the default one is no
longer available.
A constructor doesn't have a return type and it shares its name with the name of the
class.
W use a constructor to set the initial values for the fields.
public class Employee
{
public string firstName;
public int age;
public Employee(string name, int ageInt)
{
firstName = name;
age = ageInt;
}
}
We can also use primary constructor which has been introduced with C# 12.
public class Employee(string name, int ageInt)
{
}
Just like mothods, constructors can also be overloaded, if we give each a different set of parameters.
public Employee(string first, string last, string em, DateTime bd) : this(first, last, em, bd, 0)
{ } //4 parameters
public Employee(string first, string last, string em, DateTime bd, double rate)
{ // 5 parameters
firstName = first;
lastName = last;
email = em;
hourlyRate = rate;
birthDay = bd;
}
Creating an instance of a class
An instance of a class is called an object. We create a new instance of a class with the new operator.
Let's create an object of a class from the example above.
We will use the construvtor in order to do that.
Employee employee = new Employee("Lena", 55);
variable type | variable name = new (class ← it can be omitted) | arguments
Let's invoke a method on the created Employee.
employee.PerformWork();
Let's change a field.
employee.firstName = "Magdalena";
Let's return a value from a method.
int salary = employee.ReceiveWage();
Roll dice example:
Random dice = new Random();
OR (in the later versions of .NET Runtime)
Random dice = new();
Some methods require you to create an instance of a class before you call them.
This line would cause an error:
int roll = Random.Next();
To get rid of this error, we need to create an instance of the Random class (before accessing the Next() method).
Random dice = new();
int roll = dice.Next(1, 7);
Console.WriteLine(roll);
// random int between 1 and 6
Enumerations
Enums are a special class that contains a set of named integer constants.
public enum Colors {
Red, // 0 (if no other value has been assigned)
Green, // 1
Blue, // 2
Brown, // 3
Pink // 4
}
OR we can specify the integer values for our colors ourselves
public enum Colors {
Red = 10, // 10
Green = 12, // 12
Blue = 13, // 13
Brown = 24, // 24
Pink = 35 // 35
}
Let's access one of the colour names:
Console.WriteLine(Colors.Red + "is my favourite colour.");
// Red is my favourite colour.
Let's access the integer values.
Console.WriteLine(Colors.Pink + "'s integer value is " + (int)Colors.Pink);
// Pink's integer value is 35
Struct
Struct is a value type and represents a custom data structure. We can create it with a new keyword. Can contain methods and other members.
struct WorkTask
{
public string description;
public int hours;
public void PerformWorkTask()
{
Console.WriteLine($"Task: {description} has been performed. It took {hours} hours.")
}
}
WorkTask task;
task.description = "Preparing documents";
task.hours = 2;
task.PerformWorkTask(); //Task: Preparing documents has been performed. It took 2 hours.
Lists of data
Arrays
- * all variables must be of the same type,
- * accessed through index
- * are reference type, stored on the heap,
- * arrays are created when we use the keyword new
- * array size is set while initialization
Initiating an array:
string[] booksToRead;
string[] booksToRead = new string[5]; //we need to specify the size of array
DateTime[] readingTime;
Populating an array:
string[] booksToRead = new string[5] {"Title1", "Title 2", "Title 3", "Title 4", "Title 5"};
int[] numbers = new int[] {45, 99, 555}; //we can omit size value if we pass in an initializer
int[] numbers = new int[] {45, 99, 555}; OR int[] numbers = [45, 99, 555];
Let's access the elements of an array:
numbers[0] = 5;
foreach loop
foreach (int num in numbers)
{
var randomNum = new Random().Next(30);
var together = num + randomNum;
Console.WriteLine(num + ", " + randomNum + ", " + together);
}
// 5, 4, 9
99, 26, 125
555, 3, 558
The Array Base Class
- CopyTo() and Length
int[] numbers = [1, -8, 23, 11]; int lentgh = numbers.Length; int[] numbersCopy = new int[lentgh]; //we need an array to copy our array into numbers.CopyTo(numbersCopy, 0); //copy to numbersCopy, start with index 0 = copy everthing foreach (int num in numbersCopy) { var randomNum = new Random().Next(30); var together = num + randomNum; Console.WriteLine(num + ", " + randomNum + ", " + together); } // -8, 5, -3 1, 14, 15 11, 12, 23 23, 17, 40
- Sort() and Reverse()
int[] numbers = [1, -8, 23, 11]; Array.Sort(numbers); foreach (int num in numbers) { var randomNum = new Random().Next(30); var together = num + randomNum; Console.WriteLine(num + ", " + randomNum + ", " + together); } // Hello, World! -8, 1, -7 1, 13, 14 11, 10, 21 23, 0, 23
Collections
- * i.e. List
- * arrays have a lot of limitations, which collections do not
- * we don't need to specify the size of a collection - it will change dynamically
- * we use List<T> to create a collection, where T stands for type
- * all elements of a List need to be of the same type
//creating a List List<int> numbers = new List<int> { 1, 2, 3 }; OR List<int> numbers = new() { 1, 2, 3 }; OR List<int> numbers = new List<int>();
//adding to a List numbers.Add(78);
//removing from a List numbers.Remove(3);
//accessing an element int selectedEl = numbers[2]; Console.WriteLine(selectedEl); //78
//checking the size int length = numbers.Count; Console.WriteLine(length); //3
//inserting an element into a specific position numbers.Insert(0, 3000); Console.WriteLine(numbers);
//let's remove everything from the numbers collection numbers.Clear(); Console.WriteLine(numbers.Count); //0Sources:
https://learn.microsoft.com/en-us/dotnet/csharp/tour-of-csharp
https://learn.microsoft.com/en-gb/training/modules/csharp-call-methods/3-call-methods
Comments (0)
Be the first to leave a comment