C# Data Types and Core Concepts

C# categorizes data types into two main categoreis: value types and reference types

Value types include: byte, short/char, int, long, float, double, decimal, enum, struct

Reference types include: string, object, interface, delegate, array

Value types pass copies of values, while reference types pass memory addresses

When two variables have identical values, modifying one doesn't affect the other

When two variables reference the same address, modifying one affects both

object.ReferenceEquals(first, second) // Check if objects are the same instance

Converting from larger to smaller types requires explicit casting, while converting from smaller to larger types happens implicitly

All assignment and arithmetic operations can trigger automatic type conversion

Implicit conversion always transforms from smaller to larger types

Converting char to int yields ASCII values, and vice versa

Note: ASCII is a numeric encoding system for letters and symbols

Operations between identical types don't trigger automatic conversion

For example: 3/5 returns 0 because both 3 and 5 are integers, the result remains int type, not automatically converting to double

char and short have the same size but different ranges, preventing direct assignment between them

char ranges from 0 to 65535, while short ranges from -32768 to 32767

Some types require specific suffixes during assignment

decimal uses M suffix

float uses f suffix

long uses L suffix

Example:

decimal price = 3.14M

Enumerations represent a finite set of named values

Enums offer better readability than primitive types and better performance than strings

Enums are ideal for representing fixed categories like gender, nationality, or regions

Five access modifiers define visibility scopes:

private - accessible only within the declaring class

protected - accessible within the declaring class and derived classes

public - accessible from any location

internal - accessible within the current assembly

protected internal - accessible within the current assemb or derived classes

Access modifiers control accessibility and usage rights

Classes default to internal, while class members default to private

Properties encapsulate fields, ensuring data validity through get and set accessors

Get and set are essentially methods: get triggers during retrieval, set triggers during assignment

public void SetIdentifier(int value)
{
    identifier = value;
}

public int GetIdentifier()
{
    return identifier;
}

public int Identifier { get => identifier; set => identifier = value; } // Lambda expression syntax (not recommended)
public int Identifier { get; set; } = 10; // Auto-property with initializer

String formatting with placeholders

string greeting = "hello";
string target = "world";

Console.WriteLine(String.Format("{0}, {1}!", greeting, target));

When outputting statements with multiple variables, continuous concatenation becomes cumbersome. String.Format with placeholders solves this

A more convenient syntax exists:

Console.WriteLine($"{greeting}, {target}!");

Available in newer C# versions

Constructors initialize class instances

Constructors can have different access modifiers than their classes

Constructor parameters can have default values: parameters with defaults are optional, without defaults are required

When a class has constructors, object instantiation must provide corresponding parameters

public class Product
{
    int productId;
    public Product(int id)
    {
        this.productId = id; // Use 'this' to distinguish between parameter and field
    }
}

Product item = new Product(101); // Provide required int parameter

Otherwise, compilation fails

public class Product
{
    int productId;
    public Product(int id = 0)
    {
        this.productId = id; 
    }
}

Product item = new Product(); // Optional parameter allows instantiation without arguments

Method parameters can also have default values

public void DisplayMessage(string text = "default")
{
    Console.WriteLine(text + " processed");
}

Code refactoring: reuse existing code for common functionality

public Employee(int empId, string empName = "Unknown") // Initialize employee with ID and name
{
    this.EmployeeId = empId;
    this.EmployeeName = empName;
}

public Employee(int empId, string empName, string department) : this(empId, empName)
{
    this.Department = department; // Reuse base constructor, add department
}

// Method overloading example
public int Calculate(int x, int y)
{
    return x + y;
}

public int Calculate(int x, int y, int z)
{
    return Calculate(x, y) + z;
}

throw new InvalidOperationException("Custom error message");

Indexers

Indexers enable objects to be accessed using collection-like syntax

public class DataCollection
{
    private string[] items = new string[3];

    public string this[int index]
    {
        get { return items[index]; }
        set { items[index] = value; }
    }
}

static void Main()
{
    DataCollection collection = new DataCollection();
    collection[0] = "First item";
    collection[1] = "Second item";
    collection[2] = "Third item";
    
    for (int i = 0; i < 3; i++)
    {
        Console.WriteLine(collection[i]);
    }
    Console.ReadLine();
}

Indexers are syntactically similar to properties but provide array-like access to objects

Tags: C# data-types programming-fundamentals value-types reference-types

Posted on Sun, 17 May 2026 02:50:26 +0000 by Rai_de