What is the CLR, and how does a C# program run?
The CLR (Common Language Runtime) is the .NET virtual machine: it loads assemblies, JIT-compiles their IL to native code, runs the garbage collector and enforces type safety. The JIT compiles each method on its first call; with tiered compilation (default since .NET Core 3.0), hot methods are recompiled with full optimization. Native AOT (.NET 7 and later) needs no JIT at all.
What is the difference between value types and reference types?
A value type variable holds the data and is copied on assignment; a reference type variable holds a reference to a heap object, and assignment copies the reference. Structs and enums are value types; classes,
string, arrays and delegates are reference types.Trap: value types do not always live on the stack. An
intfield of a class lives on the heap inside that object.How does garbage collection work in .NET?
The .NET GC is generational and tracing: it marks objects reachable from roots (locals, statics, GC handles), frees the rest and usually compacts the survivors. New objects start in Gen 0, collected often and cheaply; survivors move to Gen 1 and Gen 2, where collections are expensive. Objects of 85,000 bytes or more go to the large object heap, which is usually swept rather than compacted; see the large object heap docs.
What is
IDisposable, and what does theusingstatement do?IDisposable.Dispose()releases resources the GC does not manage, such as file handles and connections, at a known moment. Ausingblock compiles totryandfinally, soDispose()runs even on an exception.C#using System; class Connection : IDisposable { private readonly string name; public Connection(string name) { this.name = name; Console.WriteLine("open " + name); } public void Dispose() { Console.WriteLine("close " + name); } } class Program { static void Main() { try { using (var a = new Connection("A")) using (var b = new Connection("B")) { throw new Exception("query failed"); } } catch (Exception ex) { Console.WriteLine("caught: " + ex.Message); } } }Resources are disposed in reverse order, before the
catchruns. See using statement.What is the difference between a finalizer and
Dispose, and what is the dispose pattern?Disposeis called by your code to release resources deterministically; a finalizer (~MyClass()) is called by the GC at some unknown later time, as a safety net.class NativeBuffer : IDisposable { private IntPtr handle; // unmanaged memory private bool disposed; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); // finalizer no longer needed } protected virtual void Dispose(bool disposing) { if (disposed) return; if (disposing) { /* dispose other IDisposable fields here */ } Marshal.FreeHGlobal(handle); // free unmanaged resources in both paths disposed = true; } ~NativeBuffer() { Dispose(false); } }Objects with a finalizer survive an extra GC, so add one only when the class owns an unmanaged handle directly. Modern code wraps the handle in a
SafeHandleinstead.What is the difference between an assembly and a namespace?
An assembly is a versioned unit of deployment, a
.dllor.exewith IL and metadata; a namespace is a logical prefix for type names. One assembly can hold many namespaces and one namespace can span assemblies. Only the assembly affects access, throughinternal.What is the difference between .NET Framework, .NET Core and .NET?
.NET Framework is the original Windows-only runtime, stopped at 4.8.x, and its default C# version is 7.3 (see C# language versioning). .NET Core was the cross-platform, open-source rewrite, called .NET from version 5; it gets the latest C# and a yearly release, .NET 10 is the current long-term support version, and .NET 8 support ends in November 2026.
Why must you override
GetHashCodewhen you overrideEquals?DictionaryandHashSetuse the hash code to find the bucket and only then callEquals, so equal objects with different hash codes are treated as different.C#using System; using System.Collections.Generic; class Point { public int X, Y; public Point(int x, int y) { X = x; Y = y; } public override bool Equals(object obj) { var p = obj as Point; return p != null && p.X == X && p.Y == Y; } // GetHashCode not overridden: each object keeps its own reference-based hash } class FixedPoint : Point { public FixedPoint(int x, int y) : base(x, y) { } public override bool Equals(object obj) { return base.Equals(obj); } public override int GetHashCode() { return X * 31 + Y; } } class Program { static void Main() { var broken = new HashSet<Point> { new Point(1, 2), new Point(1, 2) }; var correct = new HashSet<Point> { new FixedPoint(1, 2), new FixedPoint(1, 2) }; Console.WriteLine(broken.Count + " " + correct.Count); } }Equal objects must return equal hash codes. Write
HashCode.Combine(X, Y), or use arecord, which generates both methods.What is the difference between a shallow copy and a deep copy in C#?
A shallow copy copies the fields as they are, so reference fields still point at the same objects; a deep copy also copies those objects.
MemberwiseClone()is shallow.C#using System; using System.Collections.Generic; class Order { public string Id; public List<string> Items = new List<string>(); public Order ShallowCopy() { return (Order)MemberwiseClone(); } public Order DeepCopy() { var copy = (Order)MemberwiseClone(); copy.Items = new List<string>(Items); // copy the list too return copy; } } class Program { static void Main() { var original = new Order { Id = "A1" }; original.Items.Add("pen"); var shallow = original.ShallowCopy(); var deep = original.DeepCopy(); original.Items.Add("book"); Console.WriteLine(shallow.Items.Count + " " + deep.Items.Count); Console.WriteLine(ReferenceEquals(shallow.Items, original.Items)); } }The shallow copy shares the list and sees the new item (
2); the deep copy does not (1).What is the difference between the stack and the heap in .NET?
The stack holds method frames (parameters, locals, return addresses), one stack per thread, freed when the method returns. The heap holds class instances, arrays and boxed values, is shared by all threads, and is freed by the GC. Deep recursion ends in
StackOverflowException, which cannot be caught.
.NET Interview Questions
How a C# program runs: the CLR, the JIT, memory, garbage collection and IDisposable.
10 questions