DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Securing Your Software Supply Chain with JFrog and Azure
Register Today

Trending

  • Essential Architecture Framework: In the World of Overengineering, Being Essential Is the Answer
  • The SPACE Framework for Developer Productivity
  • Implementing a Serverless DevOps Pipeline With AWS Lambda and CodePipeline
  • Understanding Dependencies...Visually!

Trending

  • Essential Architecture Framework: In the World of Overengineering, Being Essential Is the Answer
  • The SPACE Framework for Developer Productivity
  • Implementing a Serverless DevOps Pipeline With AWS Lambda and CodePipeline
  • Understanding Dependencies...Visually!

Reader Challenge - Fault Handlers in C#

Bart De Smet user avatar by
Bart De Smet
·
Dec. 24, 09 · News
Like (0)
Save
Tweet
Share
3.99K Views

Join the DZone community and get the full member experience.

Join For Free

The CLR’s exception handling facilities provide for protected blocks (“try”) one can associate a handler with. There are four kinds of handlers, and exactly one can be associated with a protected block (but nesting can be used to associate multiple handlers with a block of code):

  • A finally handler is executed whenever the block is exited, regardless of whether this happened by normal control flow or an unhandled exception. C# exposes this using the finally keyword.
  • A type-filtered handler handles an exception of a specified class or any of its subclasses. Better known as a “catch block”, C# provides this through its catch keyword.
  • A user-filtered handler runs user-specified code to determine whether the exception should be ignored, handled by the associated handler, or passed on to the next protected block. C# doesn’t expose this, but Visual Basic does by means of its When keyword.
  • A fault handler is executed if an exception occurs, but not on completion of normal control flow. Neither C# nor Visual Basic provide a fault handler language feature.

In this reader challenge, we’re going to focus on fault handlers. Due to their lack of language surface, their effect is often mimicked by using some local state to determine whether the protected block exited gracefully or not:

    bool success = false;
try
{
// Do stuff
success = true;
}
finally
{
if (!success)
{
// There was a fault. Do something special.
}
// Fault or not; this is what finally does.
}

If an exception happens during “Do stuff”, we end up in the finally block and come to conclude success was never set to true. This indicates an error happened, and we should handle the fault case. However, this technique can get a bit tricky when there are different paths exiting the try block: one could return from the enclosing method in various places, requiring the “success = true” code to be sprinkled around. This is exactly what exception handling was designed for: reducing clutter in your code that has to do with error condition/code tracking. So, we’re defeating that purpose.

Today’s challenge is to create a true fault handler in C#, just for the sake of it. This is merely a brain teaser, encouraging readers to find out what happens behind the scenes of compiled C# code. We won’t be addressing certain concerns like non-local return (the case I mentioned above) but will be hunting for the true “fault” handler treasure hidden deeply in the C# compiler’s IL code emitter. The operational specification is the following:

    var f = Fault(() => Console.WriteLine("Okay"),
() => Console.WriteLine("Fault"));
f();
Console.WriteLine();

var g = Fault(() => { throw new Exception("Oops"); },
() => Console.WriteLine("Fault"));
try
{
g();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}

The above should produce the following output:

    Okay

Fault
System.Exception: Oops
at Program.<Main>b__2()
(I won’t reveal the secrets here yet…)
at Program.Main()

Action f illustrates the non-exceptional case where the fault handler is not invoked (a finally handler would get invoked). Action g illustrates the exceptional case where the fault handler gets invoked and the exception bubbles up to the catch-block surrounding its invocation.

It’s strictly forbidden to use local state in Fault (or a method it calls) to track the successful execution of the protected block. Therefore, the below is an invalid solution:

static Action Fault(Action protectedBlock, Action faultHandler)
{
return () =>
{
bool success = false;
try
{
protectedBlock();
success = true;
}
finally
{
if (!success)
faultHandler();
}
};
}

Moreover, execution of your Fault method should really use a fault handler as encountered in IL code. It should be a fault handler, not mimic one. In addition, you should not go for a solution where you write a Fault method in ILASM by hand and link it as a netmodule in a C# project, using al.exe:

    .class private FaultClosure
{
.field class [System.Core]System.Action protectedBlock
.field class [System.Core]System.Action faultHandler

.method void .ctor()
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}

.method void Do()
{
.try
{
ldarg.0
ldfld class [System.Core]System.Action Program/FaultClosure::protectedBlock
callvirt instance void [System.Core]System.Action::Invoke()
leave.s END
}
fault
{
ldarg.0
ldfld class [System.Core]System.Action Program/FaultClosure::faultHandler
callvirt instance void [System.Core]System.Action::Invoke()
endfault
}
END: ret
}
}

.method static class [System.Core]System.Action Fault(class [System.Core]System.Action protectedBlock, class [System.Core]System.Action faultHandler)
{
.locals init (class Program/FaultClosure V_0)
newobj void Program/FaultClosure::.ctor()
stloc.0
ldloc.0
ldarg.0
stfld class [System.Core]System.Action Program/FaultClosure::protectedBlock
ldloc.0
ldarg.1
stfld class [System.Core]System.Action Program/FaultClosure::faultHandler
ldloc.0
ldftn instance void Program/FaultClosure::Do()
newobj void [System.Core]System.Action::.ctor(object, native int)
ret
}

Again, this exercise is just for fun with no profit other than brain stimulation. Hint: what C# 2.0 or later feature may cause a “fault” block to be emitted (i.e. if you ildasm a compiled valid C# application, you can find a “fault” keyword)?

Happy holidays!

 

Fault (technology) csharp Blocks

Published at DZone with permission of Bart De Smet, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Essential Architecture Framework: In the World of Overengineering, Being Essential Is the Answer
  • The SPACE Framework for Developer Productivity
  • Implementing a Serverless DevOps Pipeline With AWS Lambda and CodePipeline
  • Understanding Dependencies...Visually!

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: