.Net Core Fundamentals with C# Primitive and Reference types
| . |
PART 1 – C# Primitive (Value) Types
✅ What Are Primitive (Value) Types?
Primitive types store the actual value directly in memory (Stack memory).
Each variable has its own independent copy.
🔹 Common Primitive Types
| Type | Used For | Business Example |
|---|---|---|
| int | Whole numbers | Order count |
| decimal | Money values | Invoice total |
| double | Calculations | Analytics |
| bool | True/False | Payment status |
| char | Single character | Grade |
| DateTime | Date/time | Order date |
Real-Time Business Example – E-Commerce Order
int quantity = 2;
decimal price = 1500m;
decimal totalAmount = quantity * price;
bool isPaid = false;
Why primitive?
- Quantity is just a number.
- Total amount is just a value.
- No need for complex structure.
Important Behavior (Value Copy)
int x = 10;
int y = x;
y = 20;
Console.WriteLine(x); // 10
Console.WriteLine(y); // 20
Each variable has its own copy.
When Should You Use Primitive Types?
Use them when:
✔ You store simple data
✔ You don’t need complex behavior
✔ You want better performance
✔ No object relationship required
Examples:
- Counting users
- Calculating salary
- Checking login status
- Tracking stock quantity
PART 2 – Reference Types
✅ What Are Reference Types?
Reference types store a memory address (reference), not the actual value.
Actual object lives in Heap memory.
🔹 Common Reference Types
| Type | Example |
|---|---|
| class | User, Order, Product |
| string | Customer name |
| array | List of products |
| List<T> | Collection of users |
| object | Base type |
Real-Time Business Example – Customer Object
class Customer
{
public string Name;
public int Age;
}
Customer c1 = new Customer();
c1.Name = "Jagan";
Customer c2 = c1;
c2.Name = "Raj";
Console.WriteLine(c1.Name); // Raj
Business Scenario – Order Processing
In real-world systems (like your .NET API):\
class Order
{
public int OrderId;
public decimal Amount;
}
You use reference type (class) because:
- It contains multiple properties
- It represents a real-world entity
- You may pass it between layers (Controller → Service → Repository)
🔹 When Should You Use Reference Types?
Use them when:
✔ Modeling real-world entities
✔ Storing multiple related values
✔ Passing data between layers
✔ Building APIs / Web apps
Examples:
- User
- Product
- Order
- Invoice
- Employee
🔷 Difference: Primitive vs Reference
| Feature | Primitive | Reference |
|---|---|---|
| Memory | Stack | Heap |
| Copy behavior | Value copied | Address copied |
| Performance | Faster | Slightly slower |
| Used for | Simple values | Complex objects |
🔷 PART 3 – Conditional Constructs
Used for decision-making.
1️⃣ if Statement
Business Use Case – Login Validation
bool isAuthenticated = true;
if(isAuthenticated)
{
Console.WriteLine("Access Granted");
}
When to use?
✔ Single condition check
✔ Simple validation
2️⃣ if-else
Business Use Case – Payment Status
bool paymentSuccess = false;
if(paymentSuccess)
{
Console.WriteLine("Order Confirmed");
}
else
{
Console.WriteLine("Payment Failed");
}
if-else if Ladder
Business Use Case – Tax Calculation
decimal salary = 80000;
if(salary > 100000)
{
Console.WriteLine("30% Tax");
}
else if(salary > 50000)
{
Console.WriteLine("20% Tax");
}
else
{
Console.WriteLine("10% Tax");
}
When to use?
✔ Multiple range conditions
✔ Business rule validations
switch Statement
Business Use Case – Order Status
string status = "Shipped";
switch(status)
{
case "Pending":
Console.WriteLine("Order is pending");
break;
case "Shipped":
Console.WriteLine("Order shipped");
break;
default:
Console.WriteLine("Unknown status");
break;
}
When to use?
✔ Fixed known values
✔ Cleaner than many if-else
PART 4 – Loops in C#
Loops repeat logic.
1️⃣ for Loop
Used when iteration count is known.
Business Example – Process Orders
for(int i = 1; i <= 5; i++)
{
Console.WriteLine("Processing Order: " + i);
}
When to use?
✔ Known count
✔ Index-based processing
while Loop
Used when condition-based.
Business Example – Retry Payment
int attempts = 0;
while(attempts < 3)
{
Console.WriteLine("Retrying Payment...");
attempts++;
}
while Loop
Used when condition-based.
Business Example – Retry Payment
int attempts = 0;
while(attempts < 3)
{
Console.WriteLine("Retrying Payment...");
attempts++;
}
do-while Loop
Runs at least once.
Business Example – ATM Menu
int choice;
do
{
Console.WriteLine("1. Withdraw");
Console.WriteLine("2. Exit");
choice = Convert.ToInt32(Console.ReadLine());
} while(choice != 2);
foreach Loop
Used for collections.
Business Example – List of Customers
string[] customers = { "Ram", "Sam", "Jagan" };
foreach(string customer in customers)
{
Console.WriteLine(customer);
}
REAL-TIME MINI PROJECT – Billing System
decimal total = 0;
for(int i = 1; i <= 3; i++)
{
Console.Write("Enter product price: ");
decimal price = Convert.ToDecimal(Console.ReadLine());
total += price;
}
if(total > 5000)
{
total = total * 0.9m; // 10% discount
}
Console.WriteLine("Final Bill: " + total);
Concepts used:
- Primitive types
- Loop
- Condition
When Should You Use What? (Practical Decision Guide)
| Scenario | Use |
|---|---|
| Simple number calculation | Primitive |
| Real-world entity modeling | Reference type |
| Single condition | if |
| Multiple fixed values | switch |
| Known iteration count | for |
| Unknown iteration count | while |
| Collection traversal | foreach |
In Enterprise .NET Projects (Real Business)
In real-world systems like:
- E-commerce
- Banking
- Healthcare
- SaaS platforms
- Cloud APIs
You will:
✔ Use primitive types for calculations
✔ Use reference types for domain models
✔ Use conditions for business rules
✔ Use loops for batch processing
✔ Combine everything in Controllers & Services
SECTION 2 :Data Structures for .NET Developers
(Concept + When to Use + Business Use Case + Real-Time Example)
As a .NET developer, especially if you’re building APIs, microservices, SaaS apps, or enterprise systems, choosing the right data structure directly impacts performance, scalability, and memory usage.
I’ll explain:
- ✅ What it is
- ✅ When to use it
- ✅ Business use case
- ✅ Real-time C# example
- ✅ Performance considerations
1️⃣ Array
🔹 Concept
Fixed-size collection of same data type stored in contiguous memory.
int[] numbers = new int[3] { 10, 20, 30 };
When to Use
✔ Fixed number of items
✔ High performance needed
✔ Index-based access required
Business Use Case
Monthly sales for 12 months.
decimal[] monthlySales = new decimal[12];
monthlySales[0] = 100000m; // January
Performance
- Access: O(1)
- Insert/Delete: Not flexible
2️⃣ List<T>
🔹 Concept
Dynamic version of Array (Resizable collection).
List<string> users = new List<string>();
users.Add("Jagan");
When to Use
✔ Data size unknown
✔ Frequent add/remove
✔ API responses
Business Use Case
Fetching users from database.
List<string> customers = new List<string>
{
"Ram",
"Sam",
"Jagan"
};
Why Used in Enterprise?
Most commonly used structure in:
- ASP.NET Core APIs
- EF Core queries
- Microservices responses
2.Dictionary<TKey, TValue>
🔹 Concept
Stores data as key-value pairs.
Fast lookups.
Dictionary<int, string> employees = new Dictionary<int, string>();
employees.Add(101, "Raj");
When to Use
✔ Fast searching by key
✔ Mapping relationships
✔ Caching
Business Use Case – Product Lookup
Dictionary<int, string> productCatalog = new Dictionary<int, string>
{
{1, "Laptop"},
{2, "Mobile"}
};
Console.WriteLine(productCatalog[1]); // Laptop
Performance
- Lookup: O(1)
- Ideal for high-performance APIs
4.HashSet<T>
🔹 Concept
Stores unique values only.
HashSet<string> emails = new HashSet<string>();
emails.Add("user@gmail.com");
When to Use
✔ Avoid duplicates
✔ Fast existence check
Business Use Case
Prevent duplicate registrations.
if(!emails.Contains("user@gmail.com"))
{
emails.Add("user@gmail.com");
}
5.Stack<T>
🔹 Concept
LIFO (Last In First Out)
Stack<string> history = new Stack<string>();
history.Push("Page1");
history.Push("Page2");
history.Push("Page3");
Console.WriteLine("=== STACK CONTENT (Top to Bottom) ===");
foreach (var page in history)
{
Console.WriteLine(page);
}
Console.WriteLine("\nPeek (Top Item): " + history.Peek());
Console.WriteLine("\nPopping Items:");
while (history.Count > 0)
{
Console.WriteLine("Removed: " + history.Pop());
}
When to Use
✔ Undo/Redo
✔ Navigation history
✔ Recursive operations
Business Use Case
Browser back button.
history.Push("Home");
history.Push("Products");
Console.WriteLine(history.Pop()); // Products
Queue<T>
🔹 Concept
FIFO (First In First Out)
Queue<string> supportTickets = new Queue<string>();
// Add multiple tickets
supportTickets.Enqueue("Ticket1");
supportTickets.Enqueue("Ticket2");
supportTickets.Enqueue("Ticket3");
supportTickets.Enqueue("Ticket4");
Console.WriteLine("=== ALL TICKETS IN QUEUE (Front to Rear) ===");
foreach (var ticket in supportTickets)
{
Console.WriteLine(ticket);
}
Console.WriteLine("\nNext Ticket To Process (Peek): " + supportTickets.Peek());
Console.WriteLine("\nProcessing Tickets...");
while (supportTickets.Count > 0)
{
Console.WriteLine("Resolved: " + supportTickets.Dequeue());
}
Console.WriteLine("\nRemaining Tickets Count: " + supportTickets.Count);
When to Use
✔ Task processing
✔ Request queues
✔ Order processing
🔹 Business Use Case
Customer support system.
Console.WriteLine(supportTickets.Dequeue());
7.LinkedList<T>
🔹 Concept
Nodes connected via pointers.
- In-memory caching layer
- API rate limiter
- Session management system
You need:
- Fast removal of oldest item
- Fast move-to-front operation
Scenario
- Playlist reordering
- Priority adjustment
- Real-time job scheduling
If you already have the node reference:
LinkedList browserHistory = new LinkedList();
LinkedList<string> browserHistory = new LinkedList<string>();
// Adding pages
browserHistory.AddLast("Home");
browserHistory.AddLast("Products");
browserHistory.AddLast("Cart");
// Insert page after Products
var productsNode = browserHistory.Find("Products");
if (productsNode != null)
{
browserHistory.AddAfter(productsNode, "Offers");
}
// Remove Cart page
browserHistory.Remove("Cart");
string output = "=== BROWSER HISTORY (Forward) ===\n";
foreach (var page in browserHistory)
{
output += page + "\n";
}
output += "\n=== BROWSER HISTORY (Backward) ===\n";
var current = browserHistory.Last;
while (current != null)
{
output += current.Value + "\n";
current = current.Previous;
}
Console.WriteLine(output);
// Write to file
File.WriteAllText("LinkedListOutput.txt", output);
Console.WriteLine("\nOutput written to LinkedListOutput.txt");
}
When to Use
✔ Frequent insert/delete
✔ Large dynamic datasets
Business Use Case
Playlist system where songs inserted frequently.
8.Concurrent Collections (Enterprise Level)
For multithreaded apps.
Examples:
- ConcurrentDictionary
- ConcurrentQueue
Used in:
- High traffic APIs
- Microservices
- Background jobs
Real-World Enterprise Scenario (.NET API)
Imagine you build:
✅ E-commerce API
✅ Banking system
✅ SaaS platform
You might use:
| Scenario | Data Structure |
|---|---|
| Fetch orders | List<Order> |
| Cache product | Dictionary<int, Product> |
| Prevent duplicate emails | HashSet<string> |
| Background processing | Queue<Order> |
| Undo transactions | Stack<Transaction> |
Concept-Focused Comparison
| Structure | Best For | Performance |
|---|---|---|
| Array | Fixed data | Fast |
| List | Dynamic data | Flexible |
| Dictionary | Key lookup | Very fast |
| HashSet | Unique values | Fast |
| Stack | LIFO | Controlled |
| Queue | FIFO | Sequential |
When NOT to Use
❌ Don’t use List if frequent lookups by key → use Dictionary
❌ Don’t use Array if size unknown
❌ Don’t use Dictionary if order matters
❌ Don’t use Stack for random access
Advanced Enterprise Insight (Important for Architects)
In large systems (like AWS-hosted microservices or SaaS apps):
- API Response → List<T>
- In-memory caching → Dictionary
- Redis alternative → Dictionary
- Background worker → Queue
- Idempotency check → HashSet
SECTION 3: Implementation & Usage of List<T>, Dictionary<TKey,TValue>, Queue<T> and LINQ
(Concept + Real-Time Business Example + When to Use + Performance + Pros & Cons)
This is practical, enterprise-level guidance for .NET developers building:
- ASP.NET Core APIs
- Microservices
- SaaS platforms
- High-performance backend systems
1️⃣ List<T>
🔹 Concept
List<T> is a dynamic array.
It resizes automatically when elements are added.
Internally:
Doubles capacity when full
Backed by array
List<int> numbers = new List<int>();
numbers.Add(10);
numbers.Add(20);
Real-Time Business Example – Order Management API
Imagine you fetch orders from database.
public class Order
{
public int OrderId { get; set; }
public decimal Amount { get; set; }
}
List<Order> orders = new List<Order>
{
new Order { OrderId = 1, Amount = 1000 },
new Order { OrderId = 2, Amount = 2500 }
};
When to Use
✔ When data size is unknown
✔ When order matters
✔ When returning collections from API
✔ When iteration is common
Used in:
GetAllUsers()GetOrders()- EF Core
.ToList()
Performance
| Operation | Time Complexity |
|---|---|
| Access by index | O(1) |
| Add (end) | O(1) average |
| Insert/Delete middle | O(n) |
| Search | O(n) |
Performance Optimization
Avoid repeated resizing
List<Order> orders = new List<Order>(1000); // Pre-allocate capacity
Pros
✔ Simple
✔ Maintains order
✔ Fast indexed access
✔ LINQ friendly
🔹 Cons
❌ Slow lookup
❌ Insert/delete in middle costly
❌ Not ideal for key-based search
Dictionary<TKey, TValue>
🔹 Concept
Stores key-value pairs.
Internally uses Hash Table.
Dictionary<int, string> users = new Dictionary<int, string>();
users.Add(101, "Jagan");
Real-Time Business Example – Product Cache
In high-traffic API:
List<Order> orders = new List<Order>
{
new Order { OrderId = 1, Amount = 1000 },
new Order { OrderId = 2, Amount = 2500 }
};
Dictionary<int, Order> orderCache = new Dictionary<int, Order>();
foreach (var ord in orders)
{
orderCache[ord.OrderId] = ord;
}
// Fast lookup
var order = orderCache[1];
Console.WriteLine("=== FAST LOOKUP RESULT ===");
Console.WriteLine("Order ID: " + order.OrderId);
Console.WriteLine("Amount: " + order.Amount);
}
When to Use
✔ Fast lookup required
✔ Unique keys
✔ In-memory caching
✔ Configuration mappings
Used in:
- JWT claims
- Product cache
- Feature flags
- Id → Entity mapping
🔹 Performance
| Operation | Time Complexity |
|---|---|
| Add | O(1) |
| Lookup | O(1) |
| Remove | O(1) |
Much faster than List search.
🔹 Performance Considerations
- Keys must be unique
- Good hash distribution improves speed
- Avoid large object keys
🔹 Pros
✔ Extremely fast lookup
✔ Ideal for caching
✔ Scalable
🔹 Cons
❌ No guaranteed order (unless using OrderedDictionary)
❌ More memory usage
❌ Requires unique keys
3️⃣ Queue<T>
🔹 Concept
FIFO (First In First Out)
Queue<string> tickets = new Queue<string>();
tickets.Enqueue("Ticket1");
tickets.Dequeue();
Real-Time Business Example – Order Processing Queue
Queue<Order> orderQueue = new Queue<Order>();
orderQueue.Enqueue(new Order { OrderId = 1, Amount = 500 });
orderQueue.Enqueue(new Order { OrderId = 2, Amount = 700 });
Console.WriteLine("=== ORDER PROCESSING STARTED ===");
while (orderQueue.Count > 0)
{
var order = orderQueue.Dequeue();
Console.WriteLine($"Processing Order: {order.OrderId}, Amount: {order.Amount}");
}
Console.WriteLine("=== ALL ORDERS PROCESSED ===");
}
When to Use
✔ Task processing
✔ Background workers
✔ Message handling
✔ Rate-limiting systems
Used in:
- Payment processing
- Email sending
- Job scheduling
🔹 Performance
| Operation | Time Complexity |
|---|---|
| Enqueue | O(1) |
| Dequeue | O(1) |
Very efficient for sequential processing.
🔹 Pros
✔ Maintains processing order
✔ Efficient
✔ Simple
🔹 Cons
❌ No random access
❌ Not suitable for search
4️⃣ LINQ (Language Integrated Query)
🔹 Concept
LINQ allows querying collections using SQL-like syntax.
var highValueOrders = orders
.Where(o => o.Amount > 1000)
.ToList();
Real-Time Business Example – Filtering Orders
var totalRevenue = orders.Sum(o => o.Amount);
var topOrders = orders
.Where(o => o.Amount > 2000)
.OrderByDescending(o => o.Amount)
.ToList();
When to Use
✔ Filtering
✔ Sorting
✔ Grouping
✔ Aggregation
Used heavily in:
- EF Core
- API filtering
- Reporting modules
LINQ Performance Considerations
1️⃣ Deferred Execution
var query = orders.Where(o => o.Amount > 1000);
Query not executed until:
query.ToList();
Be careful inside loops.
2️⃣ Avoid Multiple Enumerations
❌ Bad:
if(orders.Count() > 0)
{
foreach(var order in orders)
Better:
if(orders.Any())
Avoid LINQ in High-Performance Loops
Instead of:
orders.Where(o => o.Amount > 1000).ToList();
Use manual loop in performance-critical systems.
4️⃣ Use AsNoTracking() in EF Core
Improves performance in read-only queries.
Use AsNoTracking() in EF Core
Improves performance in read-only queries.
Combined Enterprise Example
High Performance API Scenario
// Step 1: Load orders
List<Order> orders = GetOrders();
// Step 2: Convert to dictionary for fast lookup
Dictionary<int, Order> orderLookup =
orders.ToDictionary(o => o.OrderId);
// Step 3: Process queue
Queue<Order> processingQueue = new Queue<Order>(orders);
// Step 4: Use LINQ for analytics
var totalRevenue = orders.Sum(o => o.Amount);
Business Decision Guide
| Scenario | Use |
|---|---|
| Return list of users | List<T> |
| Lookup by ID | Dictionary |
| Task processing | Queue |
| Filter/reporting | LINQ |
| In-memory cache | Dictionary |
| Sequential processing | Queue |
Enterprise Architecture Insight
In scalable cloud systems:
- API layer → List<T>
- Cache layer → Dictionary
- Background worker → Queue
- Reporting → LINQ
- High throughput systems → Avoid heavy LINQ chaining
🔷 Comparison Summary
| Feature | List | Dictionary | Queue |
|---|---|---|---|
| Lookup Speed | Slow | Very Fast | N/A |
| Order Maintained | Yes | No | Yes |
| Memory | Moderate | Higher | Low |
| Best For | Collections | Mapping | Processing |
🔷 Pros & Cons Summary
List
✔ Flexible
❌ Slow lookup
Dictionary
✔ Fast
❌ More memory
Queue
✔ Structured processing
❌ No random access
LINQ
✔ Clean code
❌ Can impact performance if overused
