Dotnet Concepts
Namespace
A namespace is a container that holds classes,
interfaces, structs, enums, and other namespaces. It helps organize code and
avoid naming conflicts between classes with the same name.
Purpose:
- To logically group related classes and types
- To avoid name clashes in large applications or when using external
libraries
- To improve code readability and maintainability
Common Use Cases:
- Organizing code into layers like Models, Services, Controllers,
Helpers
- Separating business logic from data access
- Grouping related utility or extension methods
Key Points:
- Defined using the namespace keyword
- Can contain multiple classes, enums, or even nested namespaces
- Can be referenced in other files using the using directive
- One file can belong to only one namespace, but a namespace can
span multiple files
Types of Namespace:
- System Namespaces – Provided by .NET (e.g., System,
System.Collections.Generic)
- User-defined - Created by developers (e.g., MyApp.Services,
CodingPracticeDotnetCore.Models)
GC (Garbage Collector):
Garbage Collector is a system in .NET that
automatically manages memory. It finds and removes objects in memory that are
no longer used by the application.
Purpose:
- Frees up unused memory
- Prevents memory leaks
- Simplifies memory management for developers
How It Works:
- The CLR tracks objects in memory
- When memory is low or after allocation, the GC runs
- It checks for unreferenced objects and reclaims that memory
- The process is automatic and runs in the background
When It Happens:
- When memory usage crosses a threshold
- When GC.Collect() is explicitly called (not recommended often)
- During idle time in background threads
CLR (Common Language Runtime)
CLR is the execution engine for .NET applications.
It handles program execution and provides important services like memory
management, security, exception handling, and type safety.
Purpose:
- Executes .NET code (CIL – Common Intermediate Language)
- Manages application lifecycle
- Provides cross-language support (e.g., C#, VB.NET, F#)
Key Services Provided by CLR:
- Memory management (via GC)
- Code execution and optimization (JIT compilation)
- Exception handling
- Security enforcement
- Thread management
- Interoperability with unmanaged code
GC vs CLR
Feature |
GC
(Garbage Collector) |
CLR
(Common Language Runtime) |
Role |
Manages
memory by cleaning unused objects |
Executes
.NET code and manages app runtime |
Scope |
Part of
CLR |
Framework
runtime environment |
Manual
Control |
Limited
(GC.Collect()) |
No manual
control |
Developer
Involvement |
No need
to manage memory manually |
Write
managed code to run on CLR |
Variable
A variable is a named storage location used to hold
data in memory during program execution. Variables are usually defined inside
methods and are local to those methods.
Purpose:
To store data
temporarily for use during method execution.
Common Use Cases:
Holding temporary
values such as counters, inputs, results inside methods.
Key Points:
- Declared inside a method or block
- Exists only while the method or block is executing
- Cannot be accessed outside the method
Example:
int count = 10; (inside a method)
Field
A field is a variable that is declared at the class
or struct level, outside of any method. Fields store data that belongs to the
object (instance) or the class (static).
Purpose:
To store the state or
data of a class or object.
Common Use Cases:
Storing values like
ID, name, or configuration within a class.
Key Points:
- Declared directly inside a class or struct
- Can be public, private, static, readonly, or const
- Accessible throughout the class
Example: private int id;
Property
A property is a member of a class that provides a
flexible mechanism to read, write, or compute the value of a private field.
Properties use get and set accessors.
Purpose:
To encapsulate and
control access to fields, often with validation or logic.
Common Use Cases:
Exposing private data
safely with read/write control.
Key Points:
- Provides controlled access to fields
- Can be read-only (get only) or read-write (get and set)
- Can include logic inside accessors
Example:
public int Age { get; set; }
Variable vs Field vs Property
Concept |
Scope/Location |
Usage |
Access
Control |
Variable |
Inside
methods |
Temporary
storage |
Method-level
only |
Field |
Inside
class |
Object
state storage |
Class-level |
Property |
Inside
class with accessors |
Encapsulates
field with logic |
Controlled
access (get/set) |
What is an enum in C#?
An enum (enumeration) is a value type that defines
a set of named constants (usually backed by integers). Defined using the enum
keyword. Backed by integer values (starting from 0 by default). Improves
readability and type safety. Supports custom integer values.
Example:
enum Status { Active, // 0 Inactive, // 1 Suspended
// 2 } Status userStatus = Status.Active;
Usages:
- Represent fixed sets: status codes, roles, types, categories.
- Replace magic numbers or string literals.
- Used in switch-case logic.
- Enhances IntelliSense and compile-time checking.
Pros:
- Improves code readability (e.g., Status.Active vs. 0).
- Enforces type safety (prevents assigning invalid values).
- Enables grouped logic using switch statements.
- Supports metadata via attributes like [Display].
Cons:
- Limited to constant values only.
- Cannot contain behavior or methods (unlike enum classes in some
other languages).
- Not suitable for dynamic lists (e.g., database-driven values).
- Requires reflection or mapping to display friendly names.
What is Reflection in C#?
Reflection provides the ability to inspect, modify,
or invoke types, properties, methods, fields, etc., at runtime. Used to read
metadata (e.g., [Display(Name = "...")] on enums). Allows dynamic
method invocation and object creation. Operates at runtime (not at
compile-time). Commonly used in frameworks, ORMs, serializers (like JSON.NET),
testing tools. Namespace: using System.Reflection;
Example:
var type = typeof(MyClass); var methods =
type.GetMethods(); foreach (var method in methods) {
Console.WriteLine(method.Name); }
Example: Get Display name from enum:
var displayName = enumVal .GetType()
.GetMember(enumVal.ToString())[0] .GetCustomAttribute()?.Name;
Usages:
- Retrieve metadata: attributes, method/property/type names.
- Dynamically create and invoke objects or members.
- Powering tools such as dependency injection, model binding, and
serializers.
Pros:
- Enables dynamic behavior when types are unknown at compile time.
- Useful in tooling: testing frameworks, serializers, dependency
injection containers.
- Supports attribute-based configurations.
Cons:
- Lower performance compared to compiled code.
- No compile-time checking; errors occur at runtime.
- May expose private or internal members (security concern).
- Adds complexity and reduces readability.
Enum + Reflection Example
Consider the enum member: [Display(Name =
"==")] Equal Using reflection, the Display(Name) value
("==") can be accessed at runtime and shown in the UI — a common and
powerful design pattern.
Enum vs Reflection
Feature |
Enum |
Reflection |
Purpose |
Define
named constants |
Inspect
or modify metadata at runtime |
Type |
Value
type |
API
(System.Reflection) |
Main Use |
Fixed
values (status, roles) |
Dynamic
type/member info |
Pros |
Readable,
type-safe |
Flexible,
dynamic |
Cons |
No
behavior, static only |
Runtime
errors, slower |
Task
In C#, a Task represents
an asynchronous operation. It is part of the System.Threading.Tasks namespace
and is used to perform operations without blocking the main thread.
Purpose:
- To run time-consuming operations asynchronously.
- Helps improve performance and responsiveness, especially in UI and
web applications.
- Supports calling asynchronous APIs like database queries, HTTP
requests, file operations, and email sending.
Common Use Cases:
- Fetching data from a database
- Making HTTP API calls
- Performing file I/O
- Sending emails or notifications
- Running background tasks in a web or desktop app
When to Use:
- When an operation takes time but doesn't need constant CPU
(I/O-bound work).
- When you want to avoid freezing the UI or blocking server threads.
- When calling external or internal async libraries/APIs.
Types:
- Task: Asynchronous method that returns nothing.
- Task<T>:
Asynchronous method that returns a result of type T.
- void: Used only in event handlers, not recommended
for general async methods.
async
In C#, the async keyword
is used to define a method that contains asynchronous operations. It enables
the method to run tasks without blocking the calling thread.
Purpose:
- Marks a method as asynchronous
- Allows use of the await keyword
inside the method
- Improves responsiveness and scalability by avoiding thread
blocking
Common Use Cases:
- Declaring a method that performs asynchronous database access
- Defining UI event handlers that perform background work
- Creating methods that call HTTP APIs asynchronously
When to Use:
- When the method includes one or more asynchronous calls
- When you want to maintain a clear, sequential flow using await
- When you want to return a Task or Task<T> from the method
Types:
- async Task –
Method is asynchronous and returns no result
- async Task<T> –
Method is asynchronous and returns a value of type T
- async void –
Use only in event handlers; not recommended elsewhere
await
In C#, the await keyword
is used to pause the execution of an async method until the awaited Task completes, without blocking the
thread.
Purpose:
- Waits for the result of an asynchronous operation
- Allows the thread to continue other work during the wait
- Simplifies asynchronous code by avoiding callbacks
Common Use Cases:
- Waiting for database queries using ToListAsync()
- Awaiting HTTP responses from an API
- Waiting for file read or write operations
When to Use:
- Inside a method marked with async
- When calling another method that returns Task or Task<T>
- When you want the code to resume after the asynchronous work
completes
Behavior:
- Does not block the thread
- Control returns to the caller while the awaited task is running
- Resumes from where it left off once the task completes
const
In C#, const is
used to declare compile-time constants. These values are set at the time of
declaration and cannot be changed later.
Purpose:
- To define fixed, unchangeable values known at compile time
- Improves performance and code clarity for constant data
Common Use Cases:
- Mathematical constants like Pi
- Default values like MaxUsers
= 100
- Fixed strings like error messages or labels
When to Use:
- When the value will never change
- When the value is known at compile time
- When you don’t need the value to be set dynamically
Key Characteristics:
- Must be initialized at the time of declaration
- Always static, even if not explicitly marked
- Cannot be used with complex types (only primitive, string, or
null)
readonly
readonly is
used to define fields that can only be assigned during declaration or inside a
constructor. It allows for run-time initialization.
Purpose:
- To create values that remain constant after object construction
- Allows different values for different instances if needed
Common Use Cases:
- Setting configuration values at runtime
- Initializing immutable fields based on constructor parameters
When to Use:
- When the value is not known at compile time
- When the value should not change after initialization
- When different instances may need different values
Key Characteristics:
- Can only be assigned in constructor or at declaration
- Can be used with any type (primitive or complex)
- Not implicitly static (can be instance-level)
Const vs Readonly
Feature |
const |
readonly |
Set Time |
Compile-time |
Runtime
(constructor) |
Modifiable |
No ,
fixed at compile time |
Only
once, during initialization |
Scope |
Always
static(global) |
Instance-level
or static |
Type
Restriction |
Primitive,
string, null |
Any
type(primitive or complex) |
Flexibility |
Less
flexible |
More
flexible for initialization |
Comments
Post a Comment