In short
C# is a statically typed, object-oriented, managed language created by Microsoft (Anders Hejlsberg, 2000) that compiles to Intermediate Language (IL) and runs on the .NET runtime. .NET is the platform around it - a runtime (CLR), a Base Class Library, and tooling (dotnet CLI, NuGet, Visual Studio) - and since .NET Core it is cross-platform and open source. BCA and MCA syllabi examine C# and .NET as a full paper (CLR architecture, value vs reference types, delegates, LINQ, ADO.NET, ASP.NET), and placement tests ask it in the same breath as Java. It is a mainstream hiring skill in India - TCS, Infosys, Wipro, Cognizant, Accenture, Capgemini, LTIMindtree, HCLTech and most BFSI/insurance product teams run large .NET estates, and ASP.NET Core Web API plus SQL Server is a standard fresher job description.
Explained
.NET architecture: CLR, CTS, CLS, assemblies
- CLR (Common Language Runtime): the virtual execution engine - loads assemblies, verifies type safety, JIT-compiles IL to native code, manages memory (GC), handles exceptions, threading and security.
- Compilation is two-stage: source → MSIL/CIL + metadata (by
csc/Roslyn) → native machine code at run time by the JIT compiler, method by method, cached for the process life. This is why .NET code is portable across CPUs but needs a runtime. - CTS (Common Type System): one shared set of types, so an
intin C# andIntegerin VB.NET are the sameSystem.Int32- this enables cross-language inheritance. - CLS (Common Language Specification): the subset of CTS rules a library must obey to be callable from any .NET language (e.g. don't rely on case alone to distinguish public members, don't expose unsigned types in public APIs).
- Managed vs unmanaged code: managed code runs under CLR supervision (GC, verification); unmanaged code (C/C++, COM) does not and is reached via P/Invoke or
unsafeblocks. - Assembly: the unit of deployment and versioning - a
.dllor.execontaining IL, metadata and a manifest (identity, version, referenced assemblies). *Private* assemblies sit in the app folder; strong-named ones historically went to the GAC (.NET Framework only - not used by .NET Core/5+). - Namespace vs assembly: a namespace is a logical name grouping (
System.Collections.Generic); an assembly is a physical file. One assembly can hold many namespaces and vice versa. - Flavours: .NET Framework (Windows-only, 4.8.x, still maintained but closed to new features), .NET Core → .NET 5/6/7/8/9+ (one cross-platform unified stack; even-numbered releases are LTS - .NET 8 and .NET 10 are the LTS line, so check the current supported version before quoting one), Mono/Xamarin → .NET MAUI for mobile, and .NET Standard (a legacy API contract for library sharing, superseded by targeting
net8.0and above). - Toolchain:
dotnet new,dotnet build,dotnet run,dotnet publish; packages come from NuGet;dotnet publishcan produce framework-dependent, self-contained, single-file or AOT (ahead-of-time compiled) output.
C# language core
- Program shape: namespace → class →
static void Main(string[] args); since C# 9 top-level statements let a file hold only the body. One entry point per assembly. - Value types (
int,double,bool,char,decimal,struct,enum): hold data directly, live on the stack or inline in the containing object, copied on assignment, cannot benullunless declaredint?(Nullable<T>). - Reference types (
class,interface,delegate,string, arrays,object): the variable holds a reference to heap memory; assignment copies the reference, default value isnull. - **
System.Objectis the root** of everything;ToString(),Equals(),GetHashCode(),GetType()are inherited by all types. - Boxing / unboxing: boxing wraps a value type in a heap object (
object o = 42;), unboxing extracts it with an explicit cast (int i = (int)o;). Boxing is implicit and costly; unboxing throwsInvalidCastExceptionon a type mismatch. Generics exist largely to avoid it. - Type conversion: implicit (widening, no data loss), explicit cast (may lose data or throw),
Convert.ToInt32(),int.Parse()(throws on bad input) vsint.TryParse()(returnsbool, preferred). - **
varis compile-time type inference, not a dynamic type;dynamic** defers binding to run time. - Constants:
constis compile-time and implicitly static;readonlyis set once at run time in the constructor;static readonlyis the usual choice for reference types. - Strings:
stringis immutable - every concatenation creates a new object; useStringBuilderin loops.stringis a reference type but compares by value with==. Interpolation:$"Total is {amt:N2}"; verbatim:@"C:\data". - Parameters:
ref(in and out, must be initialised),out(out only),in(read-only reference),params(variable count), plus optional and named arguments. - Operators of note:
??null-coalescing,??=,?.null-conditional,is/as(safe cast returningnull),switchexpressions and pattern matching,=>lambda/expression body. - C# version features worth naming: generics (2.0), LINQ and lambdas (3.0),
dynamic(4.0),async/await(5.0), interpolation and expression-bodied members (6.0), tuples and local functions (7.0), nullable reference types andswitchexpressions (8.0), records and top-level statements (9.0), file-scoped namespaces (10.0), raw string literals (11.0), primary constructors and collection expressions (12.0).
OOP in C#, as C# specifically does it
- Class members: fields, properties (
public string Name { get; set; }- auto-implemented;{ get; init; }for set-once), methods, constructors, finalizer~Class(), indexersthis[int i], events, nested types. - Access modifiers:
private(default for members),public,protected,internal(same assembly),protected internal(either),private protected(both). - Inheritance: single class inheritance, multiple interface implementation.
:denotes both.basecalls the parent;sealedblocks further inheritance. - Polymorphism: the parent marks a member
virtualorabstract, the child usesoverride.new*hides* instead of overriding - a classic trick question. Method overloading is compile-time; overriding is run-time via the vtable. - **
abstract classvsinterface:** an abstract class may hold state, constructors and implementation and allows one base; an interface declares a contract (and since C# 8 may carry default implementations and static members) and a class may implement many. Prefer interfaces for capability, abstract classes for a shared partial implementation. - **
structvsclass:** struct = value type, no inheritance, no parameterless user constructor before C# 10, cheap for small immutable data (Point,decimal-like); class = reference type, full inheritance. - **
record/record struct:** concise immutable type with value-basedEquals/GetHashCode,ToStringand awithexpression for non-destructive copying - the modern choice for DTOs. - Other keywords:
partial(split a type across files - used by designers and source generators),staticclass (cannot be instantiated; holds extension methods), extension method (staticmethod withthisas the first parameter, e.g. all of LINQ).
Memory, GC and resource disposal
- Stack vs heap: value-type locals and references live on the stack frame; objects and boxed values live on the managed heap.
- Generational GC: Gen 0 (new, collected often), Gen 1 (buffer), Gen 2 (long-lived), plus the LOH (objects over ~85 KB). Collection is mark-and-sweep with compaction; survivors are promoted. The GC is non-deterministic - you cannot predict when a finalizer runs.
- **
IDisposableandusing:** unmanaged resources (files, sockets, DB connections, GDI handles) must be released deterministically -Dispose(), called byusing (var c = new SqlConnection(cs)) { }or theusing var c = ...;declaration, which compiles intotry/finally. - Dispose pattern:
Dispose(bool disposing)+GC.SuppressFinalize(this); a finalizer is only a safety net and adds cost. - Common leak sources despite GC: undetached event handlers, static collections that keep growing, timers, and unmanaged handles never disposed.
Collections, generics, LINQ and exceptions
- Arrays: fixed length, zero-based; single, multi-dimensional
int[,]and jaggedint[][]. - Generic collections (
System.Collections.Generic):List<T>,Dictionary<TKey,TValue>(hash, average O(1) lookup),HashSet<T>,Queue<T>,Stack<T>,SortedDictionary<TKey,TValue>,LinkedList<T>. Non-genericArrayList/Hashtableare legacy - they box and are not type-safe. - Generics: type parameters give compile-time type safety and no boxing; constraints
where T : class,struct,new(), an interface or a base type. Also generic methods anddefault(T). - Iterators:
IEnumerable/IEnumerator,foreach, andyield returnfor lazy sequences. - LINQ: query over objects, XML, DataSets or a database using query syntax (
from x in list where x.Fee > 50000 select x) or method syntax (list.Where(x => x.Fee > 50000)). Core operators:Where,Select,OrderBy,GroupBy,Join,First/FirstOrDefault,Any,All,Count,Sum,Average,Skip,Take,Distinct,ToList. - Deferred execution: LINQ-to-Objects builds an expression pipeline and runs only on enumeration (
foreach,ToList(),Count()); LINQ-to-Entities translates the expression tree into SQL. - Exceptions:
try / catch / finally / throw, all deriving fromSystem.Exception(Message,StackTrace,InnerException). Catch specific before general;finallyalways runs;throw;preserves the stack trace whilethrow ex;resets it. Custom exceptions derive fromException.checked/uncheckedcontrol integer overflow checking. - Async:
asyncmethods returnTask,Task<T>orValueTask;awaitreleases the thread until completion - essential for I/O in ASP.NET Core. Avoid.Result/.Wait()(deadlock risk).Task.Runis for CPU work, not for I/O.
The .NET application stack used in Indian jobs
- ASP.NET Core: cross-platform web framework - MVC (Model-View-Controller with Razor views), Web API (REST/JSON controllers, attribute routing, model binding and validation), Razor Pages, Blazor (C# in the browser via WebAssembly, or Blazor Server), minimal APIs (
app.MapGet("/health", () => "ok")), middleware pipeline, built-in dependency injection (AddSingleton,AddScoped,AddTransient), configuration fromappsettings.jsonand environment variables,ILogger, JWT authentication. - Data access: ADO.NET (
SqlConnection,SqlCommand,SqlDataReader,DataSet/DataAdapter, parameterised queries) and Entity Framework Core - an ORM withDbContext,DbSet<T>, LINQ queries, change tracking, migrations, and code-first or database-first modelling. Dapper is the common lightweight middle ground. - Desktop: WinForms and WPF (XAML, MVVM, data binding) still carry a large Indian maintenance and ERP market; .NET MAUI for cross-platform apps.
- Testing and quality: xUnit, NUnit, MSTest, Moq;
dotnet test; builds in Azure DevOps pipelines - Azure DevOps plus .NET is a very common Indian enterprise pairing. - Interop and legacy: many Indian BFSI systems are .NET Framework 4.x on IIS and Windows Server with SQL Server; migration to .NET 8+ and containers is active fresher-adjacent work.
- Compliance context for .NET business applications in India: GST invoicing APIs (slabs 5%, 18% and 40% since 22 September 2025, with the earlier 12% and 28% rates folded in), TDS/payroll modules now written against the Income-tax Act, 2025 (in force from 1 April 2026, with every section and form renumbered - verify the section number against the 2025 Act rather than reusing a 1961 reference), payroll and HR products rewritten for the four Labour Codes in force from 21 November 2025 (Code on Wages; Industrial Relations; Social Security; Occupational Safety, Health and Working Conditions), and personal-data handling under the Digital Personal Data Protection Act, 2023.
Key points
- CLR - the runtime that JIT-compiles IL, manages memory and enforces type safety.
- MSIL/CIL - CPU-independent intermediate code produced by the C# compiler, stored with metadata in an assembly.
- CTS vs CLS - CTS is the common type system enabling cross-language typing; CLS is the rule subset a library follows to be usable from every .NET language.
- Assembly - the deployment unit (
.dll/.exe) carrying IL, metadata and a manifest. - Value vs reference type - value types copy data and cannot be null (unless
int?); reference types copy the handle and default tonull. - Boxing/unboxing - value type → heap object and back; implicit one way, explicit the other, and a real performance cost.
- **
stringis immutable** - useStringBuilderfor repeated concatenation. - Property - a method pair (
get/set) that looks like a field; the standard way to expose state. - **
virtual/overridevsnew** - override replaces the base behaviour polymorphically;newonly hides it for the compile-time type. - Interface vs abstract class - many interfaces, one base class; abstract classes can hold state and constructors.
- **
structvsclass** - value semantics, no inheritance, suited to small data vs reference semantics with full OOP. - **
record** - immutable, value-equality type for DTOs, withwithexpressions. - Generics - compile-time type safety without boxing; constraints via
where. - Generational GC - Gen 0/1/2 plus LOH; non-deterministic, so use
IDisposable+usingfor unmanaged resources. - LINQ - uniform query syntax over collections and databases, with deferred execution until enumeration.
- Delegate / event - a type-safe method pointer (
Func<>,Action<>,Predicate<>); an event is a publish-subscribe wrapper over a delegate. - **
async/await** - frees the thread during I/O; the method returnsTask/Task<T>. - DI lifetimes -
Singleton(app),Scoped(per request),Transient(per resolution) in ASP.NET Core. - **
throw;vsthrow ex;** - the first preserves the original stack trace, the second destroys it.
Formulas and examples
C# and .NET has no numeric formulas; the equivalents are the definitional relations and complexity costs below.
csc) → MSIL + metadata in an assembly → (CLR JIT or AOT) → native codeLookup cost:
List<T>.Contains = O(n); Dictionary<K,V>[key] / HashSet<T>.Contains = O(1) average, O(n) worstNaive string concatenation in a loop of n items ≈ O(n²) characters copied;
StringBuilder ≈ O(n)Boxing cost per operation = 1 heap allocation + 1 copy of the value (size in bytes of the value type) + later GC work
sizeof: byte 1, short 2, int/float 4, long/double 8, decimal 16 bytes; char 2 bytes (UTF-16)Example 1 - value vs reference semantics, step by step.
struct PointS { public int X; }
class PointC { public int X; }
var s1 = new PointS { X = 10 };
var s2 = s1; // copies the value
s2.X = 99; // s1.X stays 10
var c1 = new PointC { X = 10 };
var c2 = c1; // copies the reference
c2.X = 99; // c1.X is now 99
Console.WriteLine($"{s1.X} {c1.X}"); // prints: 10 99
Step 1: s2 = s1 duplicates 4 bytes on the stack, so the two are independent. Step 2: c2 = c1 duplicates only the handle, so both names point to one heap object. Answer: 10 99.
Example 2 - string concatenation cost with real numbers. Build a 10,000-row CSV line set where each row adds 50 characters.
- Naive
s += row;- after i rows the string is 50i characters and is fully copied each time. Total characters copied = 50 × (1+2+…+10,000) = 50 × (10,000 × 10,001 / 2) = 50 × 50,005,000 = 2,500,250,000 characters, i.e. about 2.5 billion char copies and 10,000 discarded strings (≈ 5 GB of allocation at 2 bytes per char). StringBuilder- appends into a doubling buffer: 10,000 × 50 = 500,000 characters written, about 5,000× less copying.
**Answer: use StringBuilder; the naive loop is quadratic.**
Example 3 - LINQ on a placement dataset, computed.
record Student(string Name, string Branch, int Marks, decimal Package);
var list = new List<Student> {
new("Asha", "BCA", 78, 450000m),
new("Rahul", "BCA", 55, 300000m),
new("Meera", "MCA", 91, 800000m),
new("Vivek", "BCA", 64, 360000m),
new("Sana", "MCA", 48, 250000m)
};
var top = list.Where(s => s.Marks >= 60)
.OrderByDescending(s => s.Package)
.Select(s => new { s.Name, LPA = s.Package / 100000m })
.ToList();
var avgBca = list.Where(s => s.Branch == "BCA").Average(s => s.Package);
- Filter
Marks >= 60keeps Asha (78), Meera (91), Vivek (64) - 3 of 5. - Ordered by package descending: Meera ₹8,00,000 (8.0 LPA), Asha ₹4,50,000 (4.5 LPA), Vivek ₹3,60,000 (3.6 LPA).
- BCA average = (450000 + 300000 + 360000) / 3 = 1,110,000 / 3 = ₹3,70,000 (3.7 LPA).
**Example 4 - integer division, overflow and decimal for money.**
int a = 7, b = 2;
Console.WriteLine(a / b); // 3 (integer division truncates)
Console.WriteLine((double)a / b); // 3.5
Console.WriteLine(0.1 + 0.2 == 0.3); // False (binary floating point)
Console.WriteLine(0.1m + 0.2m == 0.3m);// True (decimal is base-10)
int big = int.MaxValue; // 2,147,483,647
unchecked { Console.WriteLine(big + 1); } // -2147483648 (wraps)
checked { /* big + 1 throws OverflowException */ }
GST check with decimal: invoice base ₹1,20,000 at 18% → tax = 1,20,000 × 0.18 = ₹21,600, total ₹1,41,600. With double, repeated rounding on thousands of lines drifts; **money fields use decimal.**
**Example 5 - virtual/override vs new.**
class Base { public virtual string Who() => "Base"; }
class Over : Base { public override string Who() => "Over"; }
class Hide : Base { public new string Who() => "Hide"; }
Base x = new Over(); Console.WriteLine(x.Who()); // "Over" - virtual dispatch
Base y = new Hide(); Console.WriteLine(y.Who()); // "Base" - hidden, not overridden
Console.WriteLine(((Hide)y).Who()); // "Hide"
| Aspect | .NET Framework 4.8 | .NET (Core) 5 / 6 / 7 / 8+ |
|---|---|---|
| Platform | Windows only | Windows, Linux, macOS, containers |
| Source | Closed | Open source (MIT, GitHub) |
| Web stack | ASP.NET MVC 5 / Web Forms | ASP.NET Core (MVC, Web API, Blazor, minimal APIs) |
| Deployment | Machine-wide runtime, GAC | Side-by-side, self-contained, single-file, AOT |
| CLI | MSBuild / Visual Studio | dotnet CLI, cross-platform |
| Status | Maintained, no new features | Active; even-numbered releases are LTS |
| C# | Java | |
|---|---|---|
| Runtime | CLR, IL, JIT/AOT | JVM, bytecode, JIT |
| Value types | User struct, record struct | Only primitives (value classes still evolving) |
| Properties | Native get/set | Getter/setter methods |
| Delegates and events | First-class | Functional interfaces, listeners |
| Operator overloading | Yes | No |
| Query support | LINQ built in | Streams API |
| Generics | Reified (available at run time) | Erased at compile time |
Where it is used
- IT services and BFSI: TCS, Infosys, Wipro, Cognizant, Accenture, Capgemini, LTIMindtree and HCLTech staff large .NET Framework-to-.NET 8 modernisation and ASP.NET Core Web API projects for banks, insurers and NBFCs on SQL Server and Azure.
- Product and ERP: Microsoft India (Hyderabad/Bengaluru), Zoho and many SME ERP, billing, GST-filing and hospital-management vendors ship WinForms/WPF and ASP.NET products; the Indian GST and e-invoicing integration market is largely .NET and PHP.
- Government and PSU applications: NIC and state e-governance portals, land-records, treasury and transport applications run substantial ASP.NET estates on IIS.
- Cloud and DevOps: Azure App Service, Azure Functions (C# is the first-class language), containerised .NET on AKS, with Azure DevOps or GitHub Actions pipelines.
- Game and XR development: Unity scripts are C# - a major Indian gaming, simulation and ed-tech employer.
- Job roles: .NET Developer / ASP.NET Core Developer, Full-stack .NET + Angular/React, Azure .NET Engineer, Unity Developer, Dynamics 365/Power Platform developer (C# plugins), support and maintenance engineer on legacy .NET Framework systems.
Interview questions
- Q: What is the CLR and what does it do? A: The Common Language Runtime is .NET's execution engine - it loads assemblies, JIT-compiles IL to native code, verifies type safety, and handles garbage collection, exceptions, threading and security.
- Q: Difference between a value type and a reference type? A: A value type stores its data directly and is copied on assignment; a reference type stores a reference to a heap object, so assignment copies the handle and both names see the same object.
- Q: What is boxing and why avoid it? A: Boxing wraps a value type in a heap object so it can be treated as
object; it costs an allocation and a copy on every operation, which is why generic collections are preferred overArrayList. - Q:
abstract classvsinterface? A: An abstract class can hold fields, constructors and implementation and a class may inherit only one; an interface is a contract (with optional default implementations since C# 8) and a class may implement many. - Q: Difference between
overrideandnewon a method? A:overridereplaces the virtual base implementation so a base-typed reference calls the derived method;newonly hides the base member, so a base-typed reference still calls the base method. - Q:
constvsreadonly? A:constis a compile-time literal, implicitly static and baked into callers;readonlyis assigned at run time in the field initialiser or constructor and may differ per instance. - Q: If there is a garbage collector, why does
IDisposableexist? A: The GC only reclaims managed memory and runs non-deterministically; file handles, sockets and DB connections must be released immediately, whichDispose()viausingguarantees. - Q: What is a delegate and how does it relate to an event? A: A delegate is a type-safe reference to a method with a given signature; an event is a restricted delegate field that outside code may only subscribe to or unsubscribe from, not invoke or overwrite.
- Q: What is deferred execution in LINQ? A: A LINQ query builds a pipeline (or expression tree) and executes only when enumerated - via
foreach,ToList(),Count()and similar - so the source may have changed by then and the query can run twice if enumerated twice. - Q: Difference between
throw;andthrow ex;inside a catch block? A:throw;rethrows the original exception with its stack trace intact;throw ex;resets the stack trace to the current line and loses the origin. - Q: What do
AddSingleton,AddScopedandAddTransientmean? A: In ASP.NET Core DI they give one instance for the application lifetime, one per HTTP request, and a new instance at every resolution respectively. - Q: Does
async/awaitcreate a new thread? A: No - for I/O it releases the current thread while the operation completes and resumes on a thread-pool thread; onlyTask.Rundeliberately moves work to another thread. - Q:
stringvsStringBuilder? A:stringis immutable, so each concatenation allocates a new object;StringBuildermutates an internal buffer and is the right choice for loops or large text building.
Common mistakes
- Saying C# is "compiled directly to machine code" or confusing MSIL compilation with JIT - name both stages.
- Mixing up CTS and CLS, or calling the CLR a "compiler".
- Using
==on arbitrary reference types and expecting value comparison (it works forstringandrecordonly because they override equality). - Using
double/floatfor money or GST amounts instead ofdecimal, then failing a reconciliation by paise. - Concatenating strings in a loop, or using
ArrayList/Hashtablein new code. - Catching
Exceptionwith an empty block, writingthrow ex;, or putting areturninsidefinally. - Forgetting
using/Dispose()onSqlConnection,StreamReaderorHttpClientusage patterns - and, conversely, creating a newHttpClientper call instead of usingIHttpClientFactory. - Calling
.Resultor.Wait()on aTaskin ASP.NET code, causing deadlocks, and declaringasync voidfor anything but an event handler. - Building SQL by string concatenation in ADO.NET instead of parameterised commands - an SQL-injection failure in interviews and in audits.
- Assuming
int?or any value type can benullwithoutNullable<T>, or dereferencing a nullable reference without a null check.
Related topics
Object-oriented programming concepts · Java essentials · JavaScript essentials · C++ essentials · Database management and SQL · Web development and REST APIs