1. Fundamentals & Data Types


1. C# Introduction & Setup

What is C#?

C# (pronounced "C-Sharp") is a modern, object-oriented programming language developed by Microsoft in 2000.

Key Characteristics:

  • Type-safe and memory-managed

  • Object-oriented (classes, inheritance, polymorphism)

  • Component-oriented (properties, events, attributes)

  • Compiled to Intermediate Language (IL), then JIT-compiled

  • Cross-platform (.NET Core/.NET 5+)

.NET Ecosystem Overview

.NET Framework (2002-present)  → Windows only, legacy
.NET Core (2016-2020)          → Cross-platform, modern
.NET 5/6/7/8/9 (2020-present)  → Unified platform, recommended

Relationship:

  • C# = Programming language

  • .NET = Runtime and libraries (like JRE for Java)

  • CLR = Common Language Runtime (executes IL code)

Installing Development Tools

Option 1: Visual Studio (Windows, macOS)

  • Full-featured IDE

  • Best for Windows development

  • Community Edition is free

  • Download: visualstudio.microsoft.com

Option 2: Visual Studio Code (Windows, macOS, Linux)

  • Lightweight editor

  • Install C# extension

  • Cross-platform

  • Download: code.visualstudio.com

Option 3: JetBrains Rider (Commercial)

  • Powerful cross-platform IDE

First Program Structure

Program Components:

  • using - Import namespaces

  • namespace - Organize code

  • class - Define types

  • Main() - Entry point

  • Console.WriteLine() - Output to console

Comments

Best Practice: Use comments to explain "why", not "what" (code should be self-explanatory).


2. Identifiers & Variables

Naming Rules (Enforced by Compiler)

Valid:

  • Must start with letter or underscore: name, _count

  • Can contain letters, digits, underscores: user1, first_name

  • Case-sensitive: Namename

Invalid:

  • Cannot start with digit: 1user

  • Cannot use keywords: int ❌ (unless prefixed with @: @int ✅)

  • Cannot contain spaces or special characters: first name ❌, user#1

Naming Conventions (Best Practices)

Type
Convention
Example

Local variables

camelCase

firstName, totalCount

Parameters

camelCase

userName, itemId

Private fields

_camelCase (underscore prefix)

_userCount, _isActive

Public fields

PascalCase (avoid, use properties)

UserCount

Constants

PascalCase or UPPER_CASE

MaxValue, MAX_SIZE

Properties

PascalCase

FirstName, IsActive

Methods

PascalCase

GetUserName(), Calculate()

Classes

PascalCase

UserAccount, OrderProcessor

Interfaces

IPascalCase (I prefix)

IComparable, IDisposable

Variable Declaration Patterns

var Keyword (C# 3.0+)

Implicitly typed local variables - compiler infers type from initializer.

When to Use var:

  • ✅ When type is obvious: var user = new User();

  • ✅ With LINQ queries: var results = from x in list select x;

  • ✅ With long generic types: var dict = new Dictionary<string, List<int>>();

  • ❌ When type is not clear: var result = GetData(); (what is result?)

dynamic Keyword (C# 4.0+)

Bypasses compile-time type checking - type resolved at runtime.

When to Use dynamic:

  • Interop with COM objects

  • Working with dynamic languages (Python, JavaScript)

  • JSON deserialization (avoid if possible, use strong types)

⚠️ Warning: Loses IntelliSense, compile-time safety, and performance. Use sparingly!

Constants: const vs readonly

const - Compile-Time Constant

Restrictions:

  • Value must be compile-time constant

  • Can only be applied to primitive types and strings

  • Implicitly static (no static keyword needed)

readonly - Runtime Constant

Comparison:

Feature
const
readonly

When set

Compile time

Constructor or declaration

Can use runtime values

❌ No

✅ Yes

Scope

Implicitly static

Instance or static

Types allowed

Primitives, strings

Any type

Can be changed

Never

In constructor only

Literals


3. Data Types Deep Dive

Value Types vs Reference Types

Value Types:

  • Stored directly in memory (usually stack)

  • Contain the actual data

  • Copied by value

  • Examples: int, double, bool, struct, enum

Reference Types:

  • Stored on heap, variable holds reference (pointer)

  • Copied by reference (both variables point to same object)

  • Examples: string, array, class, interface, delegate

Memory Diagram:

Copy Behavior:

Built-in Value Types Table

Integral Types

Type
Size (bytes)
Range
Default
Suffix
.NET Type

sbyte

1

-128 to 127

0

-

System.SByte

byte

1

0 to 255

0

-

System.Byte

short

2

-32,768 to 32,767

0

-

System.Int16

ushort

2

0 to 65,535

0

-

System.UInt16

int

4

-2.1B to 2.1B

0

-

System.Int32

uint

4

0 to 4.2B

0

U or u

System.UInt32

long

8

-9.2E+18 to 9.2E+18

0

L or l

System.Int64

ulong

8

0 to 1.8E+19

0

UL or ul

System.UInt64

Usage:

Floating-Point Types

Type
Size (bytes)
Precision
Range
Default
Suffix
.NET Type

float

4

7 digits

±1.5E-45 to ±3.4E+38

0.0F

F or f

System.Single

double

8

15-16 digits

±5.0E-324 to ±1.7E+308

0.0D

D or d (optional)

System.Double

decimal

16

28-29 digits

±1.0E-28 to ±7.9E+28

0.0M

M or m

System.Decimal

When to Use:

  • float - Graphics, scientific calculations (lower precision OK)

  • double - General-purpose (default for decimal literals)

  • decimal - Financial calculations, currency (no rounding errors)

Other Value Types

Type
Size (bytes)
Values
Default
.NET Type

bool

1

true, false

false

System.Boolean

char

2

Unicode character

'\0'

System.Char

String Type (Reference Type!)

Key Characteristics:

  • Immutable (cannot be changed after creation)

  • Reference type (stored on heap)

  • Sequence of characters

String vs string

Best Practice: Use lowercase string (C# convention).

String Immutability

Why Immutable?

  • Thread-safe

  • Can be shared/cached safely

  • String literals reused

Performance Impact:

String Interpolation (C# 6.0+)

Verbatim Strings (C# 1.0+)

Raw String Literals (C# 11.0+)

Object Type (The Universal Base)

Every type inherits from object (System.Object).

When to Use:

  • Collections before generics (ArrayList - legacy)

  • Truly polymorphic code (rare)

  • Usually: Use generics (List<T>) instead

Type Hierarchy Diagram

Key Points:

  • Everything inherits from object

  • Value types inherit from System.ValueType (which inherits from object)

  • Reference types directly inherit from object (or other classes)


4. Nullable Types

Problem: Value Types Can't Be Null

But sometimes you need "no value":

  • Database columns (NULL)

  • Optional parameters

  • Uninitialized state

Nullable Value Types (C# 2.0+)

All value types can be nullable:

Working with Nullable Types

Properties:

  • HasValue - bool, true if has value

  • Value - Get value (throws InvalidOperationException if null)

Null-Coalescing Operator (??) - C# 2.0+

Works with reference types too:

Null-Coalescing Assignment (??=) - C# 8.0+

Null-Conditional Operator (?.) - C# 6.0+

Nullable Reference Types (C# 8.0+)

Before C# 8.0: Reference types could always be null (by default).

C# 8.0+: Can enable nullable reference type checking.

Benefits:

  • Catch null reference bugs at compile time

  • Document intent (nullable vs non-nullable)

  • Safer code

Enable in project:


5. Enums

Enum Declaration and Usage

Enum = Named constants (enumeration type)

Explicit Values

Underlying Types

Default: int (can be any integral type)

When to use non-int:

  • Save memory (byte for small enums)

  • Interop with other systems

  • Match database column type

Flags Attribute [Flags]

Use for bitmasks - combine multiple enum values.

Best Practice for [Flags]:

Enum Methods

Bitwise Operations with Enums


6. Type Casting & Conversion

Implicit vs Explicit Casting

Implicit Casting - Automatic, no data loss

Implicit Conversion Hierarchy:

Explicit Casting - Manual, potential data loss

Cast Operator: (type)

as Operator

Safe casting - Returns null if cast fails (reference types only).

Comparison:

is Operator

Type checking

typeof Operator

Get Type object at compile time

Parse vs TryParse

Parse - Throws exception if fails

TryParse - Returns bool, safe

All numeric types have Parse/TryParse:

Convert Class Methods

Universal conversion methods

Convert vs Cast:

Boxing and Unboxing

Boxing - Value type → Object (reference type)

Unboxing - Object → Value type

Memory Impact:

Performance Cost:

Common Boxing Scenarios:


7. Operators

Arithmetic Operators

Operator
Name
Example
Result

+

Addition

5 + 3

8

-

Subtraction

5 - 3

2

*

Multiplication

5 * 3

15

/

Division

5 / 2

2 (integer division)

5.0 / 2

2.5 (floating-point)

%

Modulus (remainder)

5 % 2

1

++

Increment

x++ or ++x

Adds 1

--

Decrement

x-- or --x

Subtracts 1

Comparison Operators

Operator
Name
Example
Result

==

Equal

5 == 5

true

!=

Not equal

5 != 3

true

<

Less than

3 < 5

true

>

Greater than

5 > 3

true

<=

Less than or equal

5 <= 5

true

>=

Greater than or equal

5 >= 3

true

Logical Operators

Operator
Name
Example
Description

&&

Logical AND

a && b

True if both true

`

`

Logical OR

`a

b`

True if either true

!

Logical NOT

!a

Inverts boolean

Bitwise Operators

Operator
Name
Example
Description

&

Bitwise AND

a & b

AND each bit

`

`

Bitwise OR

`a

^

Bitwise XOR

a ^ b

XOR each bit

~

Bitwise NOT

~a

Inverts all bits

<<

Left shift

a << 2

Shift bits left

>>

Right shift

a >> 2

Shift bits right

Assignment Operators

Operator
Example
Equivalent to

=

x = 5

Assign 5 to x

+=

x += 3

x = x + 3

-=

x -= 3

x = x - 3

*=

x *= 3

x = x * 3

/=

x /= 3

x = x / 3

%=

x %= 3

x = x % 3

&=

x &= 3

x = x & 3

`

=`

`x

= 3`

`x = x

3`

^=

x ^= 3

x = x ^ 3

<<=

x <<= 2

x = x << 2

>>=

x >>= 2

x = x >> 2

Null Operators

Operator
Name
Example
Description

??

Null-coalescing

a ?? b

If a is null, use b

??=

Null-coalescing assignment

a ??= b

If a is null, assign b (C# 8.0+)

?.

Null-conditional

a?.Method()

Call if not null (C# 6.0+)

?[]

Null-conditional index

a?[0]

Access if not null (C# 6.0+)

Other Operators

Operator
Name
Example
Description

?:

Ternary

a ? b : c

If a, then b, else c

is

Type test

obj is string

Check if type

as

Type cast

obj as string

Safe cast (null if fails)

typeof

Type

typeof(int)

Get Type object

sizeof

Size

sizeof(int)

Size in bytes

nameof

Name of

nameof(variable)

Get name as string (C# 6.0+)

Operator Precedence (High to Low)

Level
Operators
Associativity

1

x.y, x?.y, x?[y], f(x), a[i], x++, x--, new, typeof, sizeof, checked, unchecked

Left

2

+x, -x, !x, ~x, ++x, --x, (T)x

Right

3

*, /, %

Left

4

+, -

Left

5

<<, >>

Left

6

<, >, <=, >=, is, as

Left

7

==, !=

Left

8

&

Left

9

^

Left

10

`

`

11

&&

Left

12

`

13

??

Right

14

?:

Right

15

=, +=, -=, *=, /=, etc.

Right

Example:


8. Scope of Variables

Local Scope (Method)

Class Scope (Fields)

Block Scope

Parameter Scope

Static Scope

Variable Shadowing (Hiding)

Scope Summary:

Scope Type
Declared
Lifetime
Access

Local

Inside method/block

Until end of block

Only in block

Parameter

Method signature

Method execution

Throughout method

Field

Class level

Object lifetime

All instance methods

Static

Class level (static)

Program lifetime

All code in class


9. params Keyword

Variable-Length Arguments

params allows passing variable number of arguments to a method.

Traditional params with Arrays (C# 1.0+)

Rules for params

  • Must be last parameter in method signature

  • Only one params parameter allowed

  • Can be combined with other parameters

params with Span<T> (C# 12.0+)

params with Collections (C# 13.0+)

Real-World Examples


Quick Reference Tables

Data Types Quick Reference

Category
Type
Size
Range
Default
Use Case

Integer

byte

1

0 to 255

0

Small positive numbers

sbyte

1

-128 to 127

0

Small signed numbers

short

2

-32K to 32K

0

Small integers

ushort

2

0 to 65K

0

Small positive integers

int

4

-2.1B to 2.1B

0

Default integer

uint

4

0 to 4.2B

0

Large positive integers

long

8

-9.2E+18 to 9.2E+18

0

Very large integers

ulong

8

0 to 1.8E+19

0

Very large positive

Float

float

4

±1.5E-45 to ±3.4E+38

0.0F

Graphics, low precision

double

8

±5E-324 to ±1.7E+308

0.0D

Default decimal

decimal

16

±1.0E-28 to ±7.9E+28

0.0M

Financial/currency

Other

bool

1

true, false

false

Boolean values

char

2

Unicode characters

'\0'

Single character

Reference

string

-

Text

null

Text/strings

object

-

Any type

null

Universal base

Type Conversion Methods

Scenario
Method
Example

String → Number

Parse()

int.Parse("123")

String → Number (safe)

TryParse()

int.TryParse("123", out int x)

Any → Any

Convert.ToXxx()

Convert.ToInt32("123")

Number → String

.ToString()

123.ToString()

Upcast (safe)

Implicit

long l = 10;

Downcast (risky)

(type)

int i = (int)longValue;

Safe reference cast

as

string s = obj as string;

Type check

is

if (obj is string)

Type check + cast

is pattern

if (obj is string s)

Operator Quick Reference

Category
Operators
Example

Arithmetic

+ - * / % ++ --

x + y, x++

Comparison

== != < > <= >=

x == y

Logical

`&&

Bitwise

`&

^ ~ << >>`

Assignment

= += -= *= /= %=

x += 5

Null

?? ??= ?. ?[]

x ?? 0, obj?.Method()

Other

?: is as typeof sizeof nameof

x ? y : z

Variable Declaration Patterns


Common Pitfalls

1. Integer Division

2. String Immutability

3. Boxing Overhead

4. Nullable Value Access

5. == vs Equals for Strings

6. Forgetting Suffix for Literals

7. Overflow Without Checking

8. Confusing = and ==


Best Practices

1. Use Meaningful Names

2. Use var Judiciously

3. Prefer Explicit Types for Primitives

4. Use const for True Constants

5. Use Nullable Reference Types (C# 8.0+)

6. Use TryParse Instead of Parse

7. Use Proper Numeric Types

8. Be Careful with Floating-Point Comparison

9. Initialize Variables

10. Use String Interpolation (C# 6.0+)


Last updated