diff --git a/csharp-advanced-topics/ExceptionHandling/ExceptionHandling.sln b/csharp-advanced-topics/ExceptionHandling/ExceptionHandling.sln
new file mode 100644
index 0000000000..4310b11094
--- /dev/null
+++ b/csharp-advanced-topics/ExceptionHandling/ExceptionHandling.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThrowVsThrowEx", "ThrowVsThrowEx\ThrowVsThrowEx.csproj", "{7E86B846-BE84-4BAA-BC9A-56872F6D9EF9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7E86B846-BE84-4BAA-BC9A-56872F6D9EF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7E86B846-BE84-4BAA-BC9A-56872F6D9EF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7E86B846-BE84-4BAA-BC9A-56872F6D9EF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7E86B846-BE84-4BAA-BC9A-56872F6D9EF9}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {BCFF6A56-AED0-439E-A464-8FB6242B29C3}
+ EndGlobalSection
+EndGlobal
diff --git a/csharp-advanced-topics/ExceptionHandling/ThrowVsThrowEx/ThrowVsThrowEx.csproj b/csharp-advanced-topics/ExceptionHandling/ThrowVsThrowEx/ThrowVsThrowEx.csproj
new file mode 100644
index 0000000000..c041c2184a
--- /dev/null
+++ b/csharp-advanced-topics/ExceptionHandling/ThrowVsThrowEx/ThrowVsThrowEx.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net6.0
+ enable
+ None
+ false
+
+
+
+
+
+
+
+
+
+
+
diff --git a/csharp-advanced-topics/ExceptionHandling/ThrowVsThrowEx/ThrowVsThrowExSamples.cs b/csharp-advanced-topics/ExceptionHandling/ThrowVsThrowEx/ThrowVsThrowExSamples.cs
new file mode 100644
index 0000000000..cd06709d9b
--- /dev/null
+++ b/csharp-advanced-topics/ExceptionHandling/ThrowVsThrowEx/ThrowVsThrowExSamples.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Metrics;
+using System.Linq;
+using System.Threading.Channels;
+using NUnit.Framework;
+
+namespace ThrowVsThrowEx
+{
+ public class ThrowVsThrowExSamples
+ {
+ [Test]
+ public void ThrowBehaviour_KeepsProperStackTrace()
+ {
+ try
+ {
+ new BusinessWorker().Work_Throw();
+ }
+ catch (Exception ex)
+ {
+ Assert.AreEqual(
+ @"System.InvalidOperationException: That's a nasty bug!
+ at ThrowVsThrowEx.ThirdPartyComponent.g__DoDangerousOperation|1_0()
+ at ThrowVsThrowEx.ThirdPartyComponent.GoDeeper()
+ at ThrowVsThrowEx.ThirdPartyComponent.DoInternalWork()
+ at ThrowVsThrowEx.BusinessWorker.Work_Throw()
+ at ThrowVsThrowEx.ThrowVsThrowExSamples.ThrowBehaviour_KeepsProperStackTrace()",
+ ex.ToString());
+
+ }
+ }
+
+ [Test]
+ public void ThrowEx_DropsTheStackTrace()
+ {
+ try
+ {
+ new BusinessWorker().Work_ThrowEx();
+ }
+ catch (Exception ex)
+ {
+ Assert.AreEqual(
+ @"System.InvalidOperationException: That's a nasty bug!
+ at ThrowVsThrowEx.BusinessWorker.Work_ThrowEx()
+ at ThrowVsThrowEx.ThrowVsThrowExSamples.ThrowEx_DropsTheStackTrace()",
+ ex.ToString());
+ }
+ }
+
+ [Test]
+ public void WrapAndThrowNewEx_KeepsTheStackTraceInTheInnerException()
+ {
+ try
+ {
+ new BusinessWorker().Work_WrapAndThrowNewEx();
+ }
+ catch (Exception ex)
+ {
+ //the stack trace of the top level exception is short
+ Assert.AreEqual(@" at ThrowVsThrowEx.BusinessWorker.Work_WrapAndThrowNewEx()
+ at ThrowVsThrowEx.ThrowVsThrowExSamples.WrapAndThrowNewEx_KeepsTheStackTraceInTheInnerException()", ex.StackTrace);
+ //however, the actual exception and it's stack trace is visible within the ex.InnerException property
+ //the full exception string also reveals all the layers of inner exceptions
+ Assert.AreEqual(
+ @"ThrowVsThrowEx.BusinessWorker+BusinessException: I am a business domain wrapper for internal exceptions.
+ ---> System.InvalidOperationException: That's a nasty bug!
+ at ThrowVsThrowEx.ThirdPartyComponent.g__DoDangerousOperation|1_0()
+ at ThrowVsThrowEx.ThirdPartyComponent.GoDeeper()
+ at ThrowVsThrowEx.ThirdPartyComponent.DoInternalWork()
+ at ThrowVsThrowEx.BusinessWorker.Work_WrapAndThrowNewEx()
+ --- End of inner exception stack trace ---
+ at ThrowVsThrowEx.BusinessWorker.Work_WrapAndThrowNewEx()
+ at ThrowVsThrowEx.ThrowVsThrowExSamples.WrapAndThrowNewEx_KeepsTheStackTraceInTheInnerException()",
+ ex.ToString());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/csharp-advanced-topics/ExceptionHandling/ThrowVsThrowEx/WorkerClasses.cs b/csharp-advanced-topics/ExceptionHandling/ThrowVsThrowEx/WorkerClasses.cs
new file mode 100644
index 0000000000..e565dc60bc
--- /dev/null
+++ b/csharp-advanced-topics/ExceptionHandling/ThrowVsThrowEx/WorkerClasses.cs
@@ -0,0 +1,75 @@
+using System;
+
+namespace ThrowVsThrowEx
+{
+ public class BusinessWorker
+ {
+ public void Work_Throw()
+ {
+ try
+ {
+ //lots of other business logic all around...
+ new ThirdPartyComponent().DoInternalWork();
+ }
+ catch (Exception ex)
+ {
+ //here we would handle 'ex' in the BusinessWorker (clean up resources, log state, call 911 etc.)
+ throw;
+ }
+ }
+
+ public void Work_ThrowEx()
+ {
+ try
+ {
+ //lots of other business logic all around...
+ new ThirdPartyComponent().DoInternalWork();
+ }
+ catch (Exception ex)
+ {
+ //here we would handle 'ex' in the BusinessWorker (clean up resources, log state, call 911 etc.)
+ throw ex;
+ }
+ }
+
+ public void Work_WrapAndThrowNewEx()
+ {
+ try
+ {
+ //lots of other business logic all around...
+ new ThirdPartyComponent().DoInternalWork();
+ }
+ catch (Exception ex)
+ {
+ //here we would handle 'ex' in the BusinessWorker (clean up resources, log state, call 911 etc.)
+ throw new BusinessException("I am a business domain wrapper for internal exceptions.", ex);
+ }
+ }
+
+ class BusinessException : Exception
+ {
+ public BusinessException(string? message, Exception? innerException) : base(message, innerException)
+ {
+ }
+ }
+
+
+ }
+
+ public class ThirdPartyComponent
+ {
+ public void DoInternalWork()
+ {
+ GoDeeper();
+ }
+
+ private void GoDeeper()
+ {
+ DoDangerousOperation();
+ void DoDangerousOperation()
+ {
+ throw new InvalidOperationException("That's a nasty bug!");
+ }
+ }
+ }
+}
\ No newline at end of file