C# Programming · Lessons 1–4

C# Programming Study Guide: Lessons 1–4

Review console applications, variables, strings, and operators through concise definitions, comparisons, and code patterns.

  • study-guide
  • csharp
  • console-applications
  • variables
  • strings
  • operators

How to use this guide

This guide condenses Lessons 1–4 into the ideas, vocabulary, comparisons, and code patterns you should be able to explain and use. Read each lesson section, trace the examples by hand, and then write a small variation without copying the code.

The ideas that connect Lessons 1–4

The lessons build a single workflow: create a C# console program, store information in appropriately typed variables, treat text as structured data, and combine values with operators to produce decisions and results. When you study, connect each syntax choice to its purpose: the type describes what a value means, the variable gives it a name, the operator transforms or compares it, and the console provides a simple path for input and output.

Lesson 1 — Creating Your First C# Console Application

C#, .NET, Visual Studio, and projects

Foundation vocabulary

A programming language is a compromise between what computers understand and what humans understand: people can read and write it, and programmers use it to create executable programs. A program is a sequence of instructions; a project is the folder and configuration that contains the files needed to build it; and an executable file is the built program that an operating system can run. A Windows program is commonly an executable that can be started from its icon; Windows executable files commonly use the .exe extension.

A pattern is a description of how an object looks; matching a pattern means recognizing that description in an object.

  • C# is the programming language: you write statements using its grammar and type system.
  • .NET supplies the runtime and class libraries that C# programs use. Modern .NET is cross-platform.
  • Visual Studio is an IDE that combines editing, project management, building, debugging, and configuration.
  • A project contains the source files and settings needed to build one application. A solution can organize one or more related projects.
  • A C# source file normally ends in .cs.

Build, run, and inspect

The normal development cycle is create a project, edit the source, build, run, and inspect the result. Building compiles the source and reports syntax or type errors. Running executes the built program. A successful build proves that the code is valid enough for the compiler; it does not prove that the program’s logic produces the intended result.

Traditional program structure

An explicit console entry point makes the major pieces visible:

using System;

namespace Program1
{
    public class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, C#!");
        }
    }
}

using System; makes names from the System namespace available without repeating the full namespace. A namespace groups related names, a class contains code, Main is the traditional starting method, braces define a block, and semicolons end statements. A console application’s framework starts executing right after the statement containing Main() and ends at the closing curly brace (}) that follows Main().

Top-level statements and console input/output

C# can also use top-level statements for a small console program. The compiler creates the entry point behind the scenes:

Console.Write("Enter your name: ");
string name = Console.ReadLine() ?? "";
Console.WriteLine($"Hello, {name}!");

Console.Write keeps the cursor on the same line; Console.WriteLine adds a line break. Console.ReadLine returns the entered line as a string and may return null, so ?? "" supplies an empty string when needed. Console.Read reads a character value and is sometimes used to pause a console window.

Comments document intent and are ignored when the program runs:

// This is a single-line comment.
/* This is a
   multi-line comment. */

Lesson 1 terms to know

C#, .NET, Visual Studio, IDE, program, .cs file, project, solution, namespace, class, Main, Console.Write, Console.WriteLine, Console.ReadLine, Console.Read, top-level statements, comment

Lesson 2 — Living with Variability — Declaring Value-Type Variables

Variables, identifiers, and initialization

A variable is a named storage location. Its type describes the kind of value it can hold, and its initializer gives it a starting value. Declaring a variable means creating it with a specific name and type, optionally assigning a value at the same time; you can picture it as a small box for storing something for later use. Declare and assign a variable before reading it. Identifiers are case-sensitive, cannot begin with a digit, and cannot be reserved keywords.

int seats = 24;
double fee = 15.50;
bool isOpen = true;
DateTime today = DateTime.Today;

Numeric types and arithmetic

The int type is a signed 32-bit integer: it stores whole numbers, including negative and positive values, in a range of roughly −2.1 billion through +2.1 billion. A signed integer holds both negative and positive values; an unsigned integer holds only non-negative values. The decimal type stores base-10 values with 28–29 significant digits, and its magnitude ranges from about 10⁻²⁸ up to about 10²⁸ (precisely, up to ±7.9 × 10²⁸). By comparison, float reaches about 10³⁸ and double about 10³⁰⁸, but both store approximations.

Use integer types for whole numbers. int is the usual default; long provides a larger range, while short and byte are useful for narrower domains or formats. Integer division discards the fractional part, so at least one operand must be fractional when you want a fractional result.

int whole = 5 / 9;                 // 0
double fraction = 5.0 / 9.0;       // approximately 0.555...
int remainder = 25 % 3;            // 1
bool isEven = 24 % 2 == 0;         // true

float and double use approximate binary floating-point storage; double is the common general-purpose choice. decimal is designed for base-10 financial calculations and uses the m suffix:

decimal price = 19.95m;
int quantity = 3;
decimal subtotal = price * quantity;

bool, char, string, and DateTime

bool stores true or false. char stores one UTF-16 code unit and uses single quotes, such as 'A'. string stores a sequence of characters and uses double quotes, such as "IST 2373".

char grade = 'A';
string message = "First line\nSecond line";
string path = @"C:\documents\files\myFile.txt";
DateTime now = DateTime.Now;
DateTime tomorrow = now.AddDays(1);
bool leapYear = DateTime.IsLeapYear(2028);

An ordinary string interprets escape sequences such as \n; a verbatim string prefixed with @ treats backslashes as literal characters. DateTime.Today represents the current date at midnight, while DateTime.Now includes the current local time.

Value types, constants, and var

Numeric types, bool, char, and DateTime are value types: assigning one variable to another copies the value. string is a reference type with immutable behavior; string operations create new string values rather than changing an existing string in place. The intrinsic variable types (such as int, double, bool, and char) are built into the processor’s handling of data; together with decimal they are called value types because the variable stores the actual data. string is neither an intrinsic type nor a value type: its variable stores a reference to the string’s data.

const declares a named value that cannot be reassigned and must be initialized immediately. var asks the compiler to infer a local variable’s type from its initializer; it remains strongly typed.

const int Capacity = 24;
var count = 5;          // inferred as int
var title = "C#";       // inferred as string

Conversions and casts

Casting a fractional value to an integer performs integer truncation: it removes the fractional part rather than rounding to the nearest whole number.

A widening conversion moves to a type that can represent all source values and can usually happen implicitly. A narrowing conversion may lose information and should be explicit.

Widening is also called promotion and narrowing is also called demotion. Types increase in capability in this order: char, int, long, float, double. So double to int is a demotion, while int to double, float to double, and long to float are promotions.

A cast is a type enclosed in parentheses and placed immediately in front of the variable or expression being converted, such as (int)10.50.

int count = 10;
double precise = count;      // implicit widening conversion

double average = 92.8;
int whole = (int)average;    // explicit narrowing cast; result is 92

The cast truncates the decimal portion; it does not round to the nearest integer.

Lesson 2 terms to know

variable, declaration, identifier, initialization, intrinsic type, signed integer, unsigned integer, int, long, short, byte, float, double, decimal, bool, char, string, DateTime, DateTime.Today, DateTime.Now, const, var, value type, reference type, widening conversion, narrowing conversion, promotion, demotion, cast, modulo

Lesson 3 — Pulling Strings

Strings are immutable sequences

A string is an ordered sequence of characters. Strings are immutable: an operation that appears to change a string returns a new string, leaving the original unchanged. Store the returned value when you need the changed text.

string original = "  C# Programming  ";
string trimmed = original.Trim();
string upper = trimmed.ToUpper();

High-use string operations

Need Common member or pattern
Find the number of characters Length
Access one position indexer, such as text[0]
Extract part of a string Substring
Search for text Contains, IndexOf
Test a beginning or ending StartsWith, EndsWith
Change case or remove outer spaces ToUpper, ToLower, Trim
Replace text Replace
Separate or combine pieces Split, Join
Insert values into a format string Format, interpolation
Join strings together +, Concat
Pad to a set width PadLeft, PadRight

Indexes start at zero. The last valid index is Length - 1. Check a string’s length before indexing or use a search method that reports whether the requested text exists.

A collection is a kind of storage box that holds multiple variables; Split produces one (an array of strings), and Join combines one into a single string. Concat joins multiple strings into one, and PadLeft adds characters at the start of a string to expand it to a set length.

Comparing strings

String.Compare("cat", "rabbit") returns -1 because cat sorts before rabbit; it returns 0 for equal strings and 1 when the first string sorts after the second. LastIndexOf searches from the end, while IndexOf searches from the beginning. IndexOfAny and LastIndexOfAny search for any character in a supplied character array and return an index or -1 when nothing is found.

string food = "cheeseburgers";                     // indexes 0–12
int a = food.IndexOfAny(new[] { 'a', 'b', 'c' });   // 0  ('c' is at index 0)
int b = food.LastIndexOf('r');                      // 11
int c = food.LastIndexOfAny(new[] { 'e', 'r' });    // 11
string d = food.Substring(6, food.Length - 7);      // "burger"

Whitespace means characters that normally do not display, such as spaces, tabs, and line breaks. Trim removes whitespace at the ends of a string; it does not remove internal spaces.

Character validation and string construction

Char.IsDigit tests whether a character is a decimal digit. A method that trims input, checks Length, loops through characters, and returns false for any non-digit is validating content rather than converting it to a number.

Substring(start, length) begins at a zero-based index and copies the requested number of characters. Replace returns a new string with matching characters or substrings changed, and Split breaks one string into an array using a delimiter:

string text = "Danger NoSmoking";
string changed = text.Replace(' ', '!');
string[] parts = "red,green,blue".Split(',');

Join performs the reverse operation by placing a separator between the items of a sequence. foreach (char c in text) visits each character in order without inserting spaces or commas.

To capitalize only the first character, convert that character to a string and append the unchanged remainder:

string result = char.ToUpper(text[0]).ToString()
    + text.Substring(1, text.Length - 1);

Use == for a straightforward value comparison when the desired comparison behavior is ordinary string equality. Equals and StringComparison make the comparison intent more explicit when case or culture matters. Do not use reference identity to decide whether two strings contain the same text.

string answer = "yes";
bool matches = answer.Equals("YES", StringComparison.OrdinalIgnoreCase);

Read, parse, and format text

String.Format uses numbered placeholders such as {0}, {1}, and {2}. Interpolation uses a $ before the opening quote and places expressions inside braces:

string formatted = String.Format("{0} times {1} equals {2}", 2, 5, 2 * 5);
string interpolated = $"{2} times {5} equals {2 * 5}";

An interpolated string combines standard text and variables or expressions to create a finalized string. A string literal is text enclosed in double quotation marks; a character literal uses single quotation marks.

Console input arrives as text. A common pipeline is read a line, validate or parse it, then use the typed result:

Console.Write("Enter a whole number: ");
string input = Console.ReadLine() ?? "";

if (int.TryParse(input, out int number))
{
    Console.WriteLine($"Double: {number * 2}");
}
else
{
    Console.WriteLine("Please enter digits.");
}

TryParse avoids an exception for ordinary invalid input. Split turns one string into an array of substrings, and Join combines a sequence into one string:

string line = "red,green,blue";
string[] colors = line.Split(',');
string display = string.Join(" | ", colors);

Interpolation ($"...") inserts expressions into a string. Format specifiers can control display, such as $"{subtotal:C}" for currency when subtotal is a numeric value.

Repeated string construction

For a small number of values, concatenation or interpolation is clear. When a loop repeatedly builds a large string, StringBuilder is usually more efficient because it is designed for incremental changes.

Lesson 3 terms to know

string, immutability, Length, index, Substring, Contains, IndexOf, LastIndexOf, IndexOfAny, StartsWith, EndsWith, Trim, Replace, Split, Join, Concat, Format, PadLeft, Equals, StringComparison, TryParse, string interpolation, collection, StringBuilder

Lesson 4 — Smooth Operators

Arithmetic and precedence

Arithmetic operators include +, -, *, /, and %. Parentheses make grouping explicit. Without parentheses, multiplication, division, and remainder are evaluated before addition and subtraction; operators at the same precedence are generally evaluated left to right.

int result = 2 + 3 * 4;       // 14
int grouped = (2 + 3) * 4;    // 20

Be aware of operand types: integer operands produce integer division, while a double or decimal operand produces a corresponding fractional calculation.

Assignment and increment operators

The assignment operator = stores a value; it does not test equality. Compound assignments combine an operation with assignment:

int score = 10;
score += 5;   // score = score + 5
score *= 2;   // score = score * 2
score++;      // add 1

++ and -- change a variable by one. In an expression, prefix form changes the value before it is used and postfix form uses the old value before changing it:

int a = 3;
int before = a++;   // before is 3; a is 4
int after = ++a;    // a is 5; after is 5

Relational and equality operators

<, >, <=, and >= compare ordering. == tests equality and != tests inequality. These operators produce a bool, which can be assigned to a variable or used in a conditional.

For calculated floating-point values, exact equality can be unreliable because float and double store approximations. Compare with an acceptable tolerance when appropriate. Use decimal when the domain requires base-10 financial precision.

Logical operators and short-circuiting

The single-bar operator | can perform Boolean OR without short-circuiting. Both true | false and true || false produce true, but | evaluates both operands while || may skip the right operand once the result is known. The same distinction applies to & versus &&. When a bool is written to the console or joined to a string, it displays as True or False (capitalized), so Console.WriteLine(true && false) prints False.

The logical operators combine Boolean expressions:

Operator Meaning
! not
&& and; both sides must be true
`
^ exclusive or; exactly one side is true

&& and || short-circuit: C# skips the right side when the left side already determines the result. This can both improve efficiency and prevent unsafe evaluation.

if (index >= 0 && index < values.Length)
{
    Console.WriteLine(values[index]);
}

Expressions, conversions, and overloads

An expression combines values, variables, operators, and method calls to produce a result. Its type matters. C# can apply implicit conversions when safe, but casts are needed when a conversion could lose information. Parentheses help both the compiler and the reader understand the intended order.

Many operators are overloaded: the same symbol can perform an operation appropriate to its operands. For example, + adds numeric values but concatenates strings when one operand is text.

int total = 2 + 3;                  // numeric addition
string label = "Total: " + total;   // string concatenation

Lesson 4 terms to know

operator, expression, precedence, associativity, +, -, *, /, %, =, compound assignment, ++, --, relational operator, equality operator, !, &&, ||, ^, short-circuit evaluation, implicit conversion, explicit cast, operator overloading