.NET Mastery
Know all concepts of software development
9/24/2026
5/29/2026
State Pattern
✅ Why we use the State Pattern (short)
- Avoids large
if/elseorswitchblocks based on state - Object behavior changes dynamically depending on its current state
- Follows clean design principles (Open/Closed, Single Responsibility)
- Makes code easier to maintain, extend, and test.
- Also validations can be done inside states ,and can prevent issues.
- Can also introduce new states, easily
✅ Key Idea
👉 Each state is a separate class
DraftState,ReviewState,PublishedState, etc.- Each class contains behavior specific to that state
- The main object (Context) just delegates work to the current state
🧠 One-line understanding
Instead of checking state with conditions, the object becomes the state by delegating to state classes.
5/20/2026
Adapter Pattern
Here is a clean, simple explanation with formatted code and key points added 👇
❌ Without Adapter
Old class:
class OldLogger
{
public void WriteLog(string message)
{
Console.WriteLine(message);
}
}
Client:
class NewApp
{
OldLogger logger = new OldLogger();
public void Process()
{
logger.WriteLog("Processing");
}
}
👉 Problem:
NewApp is directly dependent on OldLogger → tightly coupled → hard to replace or test
✅ With Adapter
Target interface:
interface ILogger
{
void Log(string message);
}
Old class (unchanged):
class OldLogger
{
public void WriteLog(string message)
{
Console.WriteLine(message);
}
}
Adapter:
class LoggerAdapter : ILogger
{
private OldLogger oldLogger;
public LoggerAdapter(OldLogger oldLogger)
{
this.oldLogger = oldLogger;
}
public void Log(string message)
{
oldLogger.WriteLog(message);
}
}
Client:
class NewApp
{
private ILogger logger;
public NewApp(ILogger logger)
{
this.logger = logger;
}
public void Process()
{
logger.Log("Processing");
}
}
Usage:
var app = new NewApp(new LoggerAdapter(new OldLogger()));
✅ Why we need Adapter
Used when an existing class cannot be changed but its method does not match what your system expects. Adapter converts one interface into another so both can work together.
✅ Use of Adapter
It helps integrate legacy code, third-party libraries, or different systems without modifying them. It keeps your main code clean because the client works only with an interface, not the actual old class.
✅ Final Idea
Without adapter → client depends on concrete class
With adapter → client depends on interface, adapter handles conversion
👉 Adapter hides incompatibility and reduces coupling in your main logic
Prototype Design Pattern
| Aspect | Without Prototype (new) | With Prototype (clone) |
|---|---|---|
| Creation | Build from scratch | Copy existing |
| Speed | ❌ Slow | ✅ Fast |
| CPU | ❌ High | ✅ Low |
| Memory | ✅ Same | ✅ Same |
| Use case | Simple objects | Complex/expensive objects |
| Risk | ✅ Safe | ⚠️ Copy issues |
🔁 Shallow vs Deep Copy
| Type | Description | Speed | Risk |
|---|---|---|---|
| Shallow | Copies references | ✅ Fast | ❌ Shared data |
| Deep | Full independent copy | ❌ Slower | ✅ Safe |
3/26/2026
Builder Pattern
Builder Pattern in C#
The Builder Pattern helps construct complex objects step-by-step. It is useful when you want to prevent creating incomplete or invalid objects. For example, just like a car should not be created without a steering wheel, your object should not be created without required fields.
Without Builder Pattern
When many parameters are required, constructors become difficult to maintain and easy to misuse.
public class User
{
public string Name { get; }
public int Age { get; }
public string Email { get; }
public string Address { get; }
public User(string name, int age, string email, string address)
{
Name = name;
Age = age;
Email = email;
Address = address;
}
}
// Hard to remember parameter order
var user = new User("Vinodh", 30, "v@example.com", "Bangalore");
With Builder Pattern (With Validation)
The Builder Pattern allows you to set values step-by-step and validate them before creating the final object.
public class User
{
public string Name { get; private set; }
public int Age { get; private set; }
public string Email { get; private set; }
public string Address { get; private set; }
private User() { }
public class Builder
{
private readonly User _user = new User();
public Builder SetName(string name)
{
_user.Name = name;
return this;
}
public Builder SetAge(int age)
{
_user.Age = age;
return this;
}
public Builder SetEmail(string email)
{
_user.Email = email;
return this;
}
public Builder SetAddress(string address)
{
_user.Address = address;
return this;
}
public User Build()
{
// Validation logic – prevents invalid object creation
if (string.IsNullOrWhiteSpace(_user.Name))
throw new Exception("Name is required.");
if (_user.Age <= 0)
throw new Exception("Age must be a positive value.");
if (string.IsNullOrWhiteSpace(_user.Email))
throw new Exception("Email is required.");
// Similar to: a car cannot be created without a steering wheel
if (string.IsNullOrWhiteSpace(_user.Address))
throw new Exception("Address cannot be empty.");
return _user;
}
}
}
Usage
var user = new User.Builder()
.SetName("Vinodh")
.SetAge(30)
.SetEmail("v@example.com")
.SetAddress("Bangalore")
.Build();
Conclusion
The Builder Pattern prevents invalid object creation through step-by-step construction and validation. Just like a car must not be built without vital parts, your objects remain consistent and safe.
10/12/2025
Big O Notation -
Big O notation is used to describe the time or space complexity of an algorithm in terms of input size. Here are the common types of Big O complexities, ordered from best (fastest) to worst (slowest) in terms of performance:
Constant Time – O(1)
- Description: The algorithm takes the same amount of time regardless of input size.
- Example: Accessing an element in an array by index.
🔹 Logarithmic Time – O(log n)
- Description: The time grows logarithmically as input size increases.
- Example: Binary search in a sorted array.
🔹 Linear Time – O(n)
- Description: Time increases linearly with input size.
- Example: Looping through an array.
🔹 Linearithmic Time – O(n log n)
- Description: A combination of linear and logarithmic growth.
- Example: Efficient sorting algorithms like Merge Sort, Quick Sort (average case).
🔹 Quadratic Time – O(n²)
- Description: Time increases with the square of the input size.
- Example: Nested loops over the same data, like Bubble Sort.
🔹 Cubic Time – O(n³)
- Description: Time increases with the cube of the input size.
- Example: Triple nested loops, such as in some matrix operations.
🔹 Exponential Time – O(2ⁿ)
- Description: Time doubles with each additional input element.
- Example: Solving the Traveling Salesman Problem using brute force.
🔹 Factorial Time – O(n!)
- Description: Time grows factorially with input size.
- Example: Generating all permutations of a set.
.NET Framework relation with Windows Version
.NET Framework
Types of .NET Platforms : While ".NET Framework" refers specifically to the original Windows-only version, there are other types in the broader ".NET" ecosystem:
Dependency Inversion Principle vs Dependency Injection
Dependency Inversion Principle
Instead of a class depending directly on another concrete class, it should depend on an interface or abstract class.This makes your code flexible, testable, and maintainable.
Easy to switch implementations (e.g., Service1, Service2). Easy to test using mocks. Follows DIP and promotes clean architecture
interface IService
{
public void ResetDevice();
}
public class Service1 : IService
{
public void ResetDevice() {// Sercice1 logic}
}
public class Service2 : IService
{
public void ResetDevice() {// Service2 logic}
}
public class Program
{
public static void Main()
{
IService service;
if(_soapVersion <= 1)
service = new Service1();
else
service = new Service2(); //easily replaceable, swithable
}
}
Without LSP:
Why the name inversion - The word "inversion" in Dependency Inversion Principle (DIP) refers to a reversal of the conventional direction of dependency in software design.
Without DIP: High-level modules (like business logic) depend on low-level modules (like database or email services).
This means the flow of control and design is top-down, and high-level logic is tightly coupled to implementation details.
With DIP: Both high-level and low-level modules depend on abstractions (interfaces or abstract classes).
The control is inverted: instead of high-level modules controlling low-level ones directly, they rely on abstractions that are implemented by low-level modules. - loosly coupled
interface IService
{
public void ResetDevice();
}
public class Service1 : IService
{
public void ResetDevice() {// Sercice1 logic}
}
public class Service2 : IService
{
public void ResetDevice() {// Service2 logic}
}
public class Program
{
public static void Main()
{
IService service;
if(_soapVersion <= 1)
service = new Service1();
else
service = new Service2(); //easily replaceable, swithable
}
}
Without LSP:Without DIP: High-level modules (like business logic) depend on low-level modules (like database or email services). This means the flow of control and design is top-down, and high-level logic is tightly coupled to implementation details.
With DIP: Both high-level and low-level modules depend on abstractions (interfaces or abstract classes). The control is inverted: instead of high-level modules controlling low-level ones directly, they rely on abstractions that are implemented by low-level modules. - loosly coupled
3/16/2025
IoC vs DI vs DIP
1.Inversion of Control (IoC)
Enables decoupling of components from their dependencies
Provides flexibility in how objects are created and managed
2.Dependency Inversion Principle (DIP)
A design guideline that specifies how modules should relate
Ensures high-level modules don't depend directly on low-level ones
Promotes abstraction-based relationships
3.Dependency Injection (DI)
A concrete technique for implementing IoC
Provides a specific mechanism for delivering dependencies
Helps achieve the goals outlined by DIP
3/15/2025
Liskov Substitution Principle
Example 1:Without LSP:Example, we have different Services, Service1 for soap version1 and Service2 for soap version2, now new feature is introduced in soap version2 called ReportFaultData() but for soap version1 it is not there, so we need to change Service1 by adding ReportFaultData() in interface and service1 should do " throw NotSupportedException("Reporting fault data is not supported");" , this leads to compile time error or we need to do nothing, and so we need to change other classes.
But if Service2 silently does nothing:
- The caller thinks the reboot happened ✅
- But it actually didn't ❌
- This creates hidden bugs, inconsistent behavior, and silent failures ❌
- The program becomes unpredictable ❌
- Debugging becomes extremely hard ❌
With LPS:Instead we will create new interface ISupportsFaultDataReporting and add the new ReportFaultData() and inherit only for Service1 class.
public interface IService
{
string GetControllerName();
void Reboot();
}
public interface IReportFaultData
{
void ReportFaultData();
}
public class Service1 : IService
{
public string GetControllerName()
{
return "Service2 Controller";
}
public void Reboot()
{
// Service2 reboot logic
}
// No ReportFaultData() — because Service1 cannot report faults
}
public class Service2 : IService, IReportFaultData
{
public string GetControllerName()
{
return "Service1 Controller";
}
public void Reboot()
{
// actual reboot logic
}
public void ReportFaultData()
{
// reporting logic
}
}
public class Program
{
public static void Main()
{
IService service;
if (_soapVersion <= 1)
service = new Service1();
else
service = new Service2();
Console.WriteLine(service.GetControllerName());
service.Reboot();
if (service is IReportFaultData reporter)
{
reporter.ReportFaultData();
}
}
}
Example 2:
Without LSP:Example, we are creating different robots, Kawasaki, Yaskawa, and ABBRobots all inheriting IRobots and have methods like Connect(), Operate() , Move(). Later say some new functionality in ABBRobots like ReportFaultData() is introduced, so we need to added ReportFaultData() in interface and other robots should do " throw NotSupportedException("Reporting fault data is not supported");" , this leads to compile time error or we need to do nothing, and so we need to change other classes.
With LPS:Instead we will create new interface ISupportsFaultDataReporting and add the new ReportFaultData() and inherit only for ABBRobots
public class ABBRobots : IRobots, ISupportsFaultDataReporting
{
}
public class Program
{
public static void Main()
{
List robots = new List{new Kawasaki(),new Yaskawa(),new ABBRobots()};
foreach (var robot in robots)
{
robot.Move();
if (robot is ISupportsFaultDataReporting faultDataReportingRobot)
{
faultDataReportingRobot.Report();
}
}
}
}
Without LSP:
Why the name substitution - The idea is that you should be able to substitute the base class with the derived class without breaking the functionality.
// Substituting base class with dereived class
Shape shape = new Rectangle(5, 10);
But if Service2 silently does nothing:
- The caller thinks the reboot happened ✅
- But it actually didn't ❌
- This creates hidden bugs, inconsistent behavior, and silent failures ❌
- The program becomes unpredictable ❌
- Debugging becomes extremely hard ❌
public interface IService
{
string GetControllerName();
void Reboot();
}
public interface IReportFaultData
{
void ReportFaultData();
}
public class Service1 : IService
{
public string GetControllerName()
{
return "Service2 Controller";
}
public void Reboot()
{
// Service2 reboot logic
}
// No ReportFaultData() — because Service1 cannot report faults
}
public class Service2 : IService, IReportFaultData
{
public string GetControllerName()
{
return "Service1 Controller";
}
public void Reboot()
{
// actual reboot logic
}
public void ReportFaultData()
{
// reporting logic
}
}
public class Program
{
public static void Main()
{
IService service;
if (_soapVersion <= 1)
service = new Service1();
else
service = new Service2();
Console.WriteLine(service.GetControllerName());
service.Reboot();
if (service is IReportFaultData reporter)
{
reporter.ReportFaultData();
}
}
}
public class ABBRobots : IRobots, ISupportsFaultDataReporting
{
}
public class Program
{
public static void Main()
{
List robots = new List{new Kawasaki(),new Yaskawa(),new ABBRobots()};
foreach (var robot in robots)
{
robot.Move();
if (robot is ISupportsFaultDataReporting faultDataReportingRobot)
{
faultDataReportingRobot.Report();
}
}
}
}
Without LSP:
// Substituting base class with dereived class
Shape shape = new Rectangle(5, 10);
2/07/2013
Model,View and View Model Patern (M V VM pattern)
The MVVM Pattern
The Model-View-ViewModel pattern can be used on all XAML platforms. Its intent is to provide a clean separation of concerns between the user interface controls and their logic.There are three core components in the MVVM pattern: the model, the view, and the view model. Each serves a distinct and separate role. The following illustration shows the relationships between the three components.
The components are decoupled from each other, thus enabling:
- Components to be swapped
- Internal implementation to be changed without affecting the others
- Components to be worked on independently
- Isolated unit testing
View
The view is responsible for defining the structure, layout, and appearance of what the user sees on the screen. Ideally, the view is defined purely with XAML, with a limited code-behind that does not contain business logic.In a Windows Phone application, a view is typically a page in the application. In addition, a view could be a sub-component of a parent view, or a DataTemplate for an object in an ItemsControl.
A view can have its own view model, or it can inherit its parent's view model. A view gets data from its view model through bindings, or invoking methods on the view model. At run time, the view changes when UI controls respond to view model properties raising change notification events.
There are several options for executing code on the view model in response to interactions on the view, such as a button click or item selection. If the control is a Command Source, the control’s Command property can be data-bound to an ICommand property on the view model. When the control’s command is invoked, the code in the view model will be executed. In addition to commands, behaviors can be attached to an object in the view and can listen for either a command to be invoked or event to be raised. In response, the behavior can then invoke an ICommand on the view model or a method on the view model.
Model
The model in MVVM is an implementation of the application's domain model that includes a data model along with business and validation logic. Examples of model objects include repositories, business objects, data transfer objects (DTOs), Plain Old CLR Objects (POCOs), and generated entity and proxy objects.View Model
The view model acts as an intermediary between the view and the model, and is responsible for handling the view logic. Typically, the view model interacts with the model by invoking methods in the model classes. The view model then provides data from the model in a form that the view can easily use. The view model retrieves data from the model and then makes the data available to the view, and may reformat the data in some way that makes it simpler for the view to handle. The view model also provides implementations of commands that a user of the application initiates in the view. For example, when a user clicks a button in the UI, that action can trigger a command in the view model. The view model may also be responsible for defining logical state changes that affect some aspect of the display in the view, such as an indication that some operation is pending.In order for the view model to participate in two-way data binding with the view, its properties must raise the PropertyChanged event.
View models satisfy this requirement by implementing the INotifyPropertyChanged interface and raising the PropertyChanged event when a property is changed. Listeners can respond appropriately to the property changes when they occur.
For collections, the view-friendly System.Collections.ObjectModel.ObservableCollection<T> is provided. This collection implements collection changed notification, relieving the developer from having to implement the INotifyCollectionChanged interface on collections.
Connecting View Models to Views
MVVM leverages the data-binding capabilities in Silverlight to manage the link between the view and view model, along with behaviors and event triggers. These capabilities limit the need to place business logic in the view's code-behind.There are many approaches to connecting a view model to a view, including direct relations and container-based approaches. However, all share the same aim, which is for the view to have a view model assigned to its DataContext property.
Views can be connected to view models in a code-behind file, or in the view itself.
Code-Behind
A view can have code in the code-behind file that results in the view model being assigned as its DataContext property. This could be as simple as a view instantiating a new view model and assigning it to its DataContext, or injecting a view model into a view using an inversion-of-control container.However, connecting a view model to a view in a code-behind file is discouraged as it can cause problems for designers in both Visual Studio and Microsoft Expression Blend® design software.
View
If a view model does not have any constructor arguments, the view model can be instantiated in the view as the view’s DataContext. A common approach to doing this is to use a view model locator. This is a resource which exposes the application’s view models as properties that individual views can data bind to. This approach means that the application has a single class that is responsible for connecting view models to views. In addition, it still leaves developers free to choose to manually perform the connection within the view model locator, or by using a dependency injection container.The Benefits of MVVM
MVVM enables a great developer-designer workflow, providing these benefits:- During the development process, developers and designers can work more independently and concurrently on their components. The designers can concentrate on the view, and if they are using Expression Blend, they can easily generate sample data to work with, while the developers can work on the view model and model components.
- The developers can create unit tests for the view model and the model without using the view. The unit tests for the view model can exercise exactly the same functionality as used by the view.
- It is easy to redesign the UI of the application without touching the code because the view is implemented entirely in XAML. A new version of the view should work with the existing view model.
- If there is an existing implementation of the model that encapsulates existing business logic, it may be difficult or risky to change. In this scenario, the view model acts as an adapter for the model classes and enables you to avoid making any major changes to the model code.
read more : http://msdn.microsoft.com/en-us/library/hh848246.aspx
11/21/2012
cannot be opened because its project type (.csproj) is not supported by this version of the application.
devenv.exe /resetskippkgs
8/27/2012
SQL Delete current database
http://sqlserver2000.databases.aspfaq.com/how-do-i-drop-a-sql-server-database.html
ALTER DATABASE myDataBase
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
DELETE DATABASE myDataBase
8/16/2012
C# difference between StringBuilder and String Object
When we use String objects to concatenate two strings , then a new copy of string object is created in memory by adding two objects , and the old string object is deleted.
So we use StringBuilder to do it in a effective way, here the concatenation is done on the exsisting string, hence the insertion is faster. Concatenation is done using Append() method
8/02/2012
Difference between null and String.Empty
8/01/2012
Understanding Reflection and static constructor
This post is mostly for you !!, to understand what Reflection and static constructor really mean ,and when are they used in .net projects.
6/19/2012
SQL Constraints
The following are the constraints:
- NOT NULL
- UNIQUE
- PRIMARY KEY
- FOREIGN KEY
- CHECK
- DEFAULT
