10 Things You Maybe Didn’t Know About C#

For my first ever post, I thought I’d list some neat things that I know about C# that might surprise the average reader, inspired by damieng’s similar post from 2012.

Before you start to read, I should point out that, at best, one or two of the ten points I show below are useful for anything other than niche applications. I just take pleasure in finding these ways to stretch the language. :) I’m not advocating you use ANY of these in production code.

Comments, suggestions, corrections and discussion are all welcome below.

1: You can create non-zero based arrays

Okay, I reckon at least a few people will know this one already, but in case you’re not one of them, the Array class has an overload of CreateInstance() that lets you specify your own lower-bounds on the array. Here’s an example that shows all the big events in my life up to now:

static void Go() {
	string[] thingsThatHappenedInMyLife = (string[]) Array.CreateInstance(typeof(string), new[] { 24 }, new[] { 1990 });

	thingsThatHappenedInMyLife.SetValue("I was born", 1990);
	thingsThatHappenedInMyLife.SetValue("I dislocated my shoulder", 1996);
	thingsThatHappenedInMyLife.SetValue("I was allowed to buy alcohol (big mistake)", 2008);
	thingsThatHappenedInMyLife.SetValue("I started a programming blog", 2013);

	for (int i = thingsThatHappenedInMyLife.GetLowerBound(0); i <= thingsThatHappenedInMyLife.GetUpperBound(0); ++i) {
		string lifeEvent = (string)thingsThatHappenedInMyLife[i];
		if (lifeEvent == null) lifeEvent = "not much happened to me";
		Console.WriteLine("In " + i + ", " + lifeEvent);
	}
}

And the output:

In 1990, I was born
In 1991, not much happened to me
In 1992, not much happened to me
In 1993, not much happened to me
In 1994, not much happened to me
In 1995, not much happened to me
In 1996, I dislocated my shoulder
In 1997, not much happened to me
In 1998, not much happened to me
In 1999, not much happened to me
In 2000, not much happened to me
In 2001, not much happened to me
In 2002, not much happened to me
In 2003, not much happened to me
In 2004, not much happened to me
In 2005, not much happened to me
In 2006, not much happened to me
In 2007, not much happened to me
In 2008, I was allowed to buy alcohol (big mistake)
In 2009, not much happened to me
In 2010, not much happened to me
In 2011, not much happened to me
In 2012, not much happened to me
In 2013, I started a programming blog

As you can see, I’ve led a pretty rock-and-roll life.

But in all seriousness, there are three reasons why you probably will never use this anyway:

  1. The biggest reason is that there is almost no code out there that expects anything other than a zero-based array (including in the .NET framework)
  2. Secondly, the CLR provides special optimizations for zero-based arrays that you forfeit once you use this.
  3. And thirdly, non-zero-arrays are not CLS-compliant, which means that other CLR languages might not be able to use them.

2: You can create unions in C#

If you don’t know what unions are, they’re a C++ construct that allows the same block of memory to be treated in a different fashion depending on the way you use it (there’s some more info on the MSDN page).

Although this has limited use in reality, I’ve thrown together a quick example:

[StructLayout(LayoutKind.Explicit)]
public struct UnionTest {
	[FieldOffset(0)]
	public uint Value;

	[FieldOffset(0)]
	public readonly byte AsByte;
}

In the code above, we are defining a simple struct (value type) that has a single unsigned integer value. Then, at the same address in memory we define a readonly byte field called AsByte.

The purpose of this example is really just to demonstrate unions in C#, but this UnionTest struct will let us take any uint value and represent it as a byte with no casting involved. Here’s an example:

public static void Go() {
	UnionTest union = new UnionTest();
	union.Value = 258;
	Console.WriteLine(union.AsByte);
}

This prints ’2′ to the console.

3: You can define extension methods with generic constraints on the extended type

What does this mean? Well, it means you can supply generic-style constraints on what object types your extension method will be visible from. Here’s an example of an extension method I made:

/// <summary>
/// Returns the target object if it is not null; or throws a NullReferenceException if it is.
/// </summary>
/// <typeparam name="T">The target object's type.</typeparam>
/// <param name="extended">The extended subject.</param>
/// <param name="exceptionMessage">The message that will be passed to the generated exception. If null, then a default message will be used.</param>
/// <returns>The object that NotNull was called on.</returns>
public static T NotNull<T>(this T extended, string exceptionMessage = null)
	where T : class {
	if (extended == null) throw new NullReferenceException(exceptionMessage ?? "Supplied " + typeof(T).Name + " must not be null!");
	else return extended;
}

I wrote the above code because I was tired of checking whether certain objects were null before using them (disclaimer: I’m not recommending anyone use this extension method, it’s just the best example I could come up with off the top of my head). Now I can write code like this:

/// <summary>
/// Welcomes the user.
/// </summary>
/// <param name="username">The user who is to be welcomed. Should never be null!</param>
public static void Go(string username) {
	Console.WriteLine(username.NotNull().ToUpper() + ", welcome!");
}

If username is null, a NullReferenceException will be thrown. However, the NotNull() method is never shown on value types (such as int) because of the generic constraint where T : class in NotNull!

This example is a bit contrived, but hopefully you can see the possibilities here- this capability means you can constrain the types that an extension method appears on in the same way you can with generics!

4: Using stackalloc is not ‘faster’ than allocating a standard array

ERRATA: This point is only true for arrays of sufficiently small size, and doesn’t adequately factor in the overhead of the garbage collector. See Sasha Goldstein’s response.

Some people (or maybe just myself) may have thought that using stackalloc to create a temporary array can be faster than allocating one on the heap. After all, this is generally held to be true in other languages. However, I wrote a test for this, and the results are somewhat surprising:

public static class Sandbox {
	private static readonly int NUM_ITERATIONS = 100000;
	private static readonly int NUM_POWERS_TO_CALCULATE = 10000;

	public static void Go() {
		Stopwatch stopwatch = Stopwatch.StartNew();
		for (int i = 0; i < NUM_ITERATIONS; ++i) {
			GetSquare(i % NUM_POWERS_TO_CALCULATE);
		}
		stopwatch.Stop();
		Console.WriteLine("Regular method: " + stopwatch.Elapsed);

		stopwatch = Stopwatch.StartNew();
		for (int i = 0; i < NUM_ITERATIONS; ++i) {
			GetSquareStack(i % NUM_POWERS_TO_CALCULATE);
		}
		stopwatch.Stop();
		Console.WriteLine("Stackalloc method: " + stopwatch.Elapsed);
	}

	public static int GetSquare(int value) {
		int[] someNumbers = new int[NUM_POWERS_TO_CALCULATE];
		for (int i = 0; i < NUM_POWERS_TO_CALCULATE; ++i) {
			someNumbers[i] = (int)Math.Pow(i, 2);
		}

		return someNumbers[value];
	}

	public unsafe static int GetSquareStack(int value) {
		int* someNumbers = stackalloc int[NUM_POWERS_TO_CALCULATE];
		for (int i = 0; i < NUM_POWERS_TO_CALCULATE; ++i) {
			*(someNumbers + i) = (int)Math.Pow(i, 2);
		}

		return *(someNumbers + value);
	}
}

Running on a release build, I get the following results:

Regular method: 00:00:40.0347039
Stackalloc method: 00:00:40.6460919

So, perhaps it was just me who thought this, but there’s no performance gain (in this example) from the use of stackalloc. So what is it good for? There are three occasions where it is sometimes sensible to use stackalloc:

  1. Allocating to the stack means that, in certain circumstances, your data is more likely to have locality of reference on the CPU cache (adding a (very) slight speed improvement, but in reality this is rarely ever going to add much of a performance boost);
  2. If you’re passing memory out to a different application or appdomain, you don’t need to pin the memory on the heap (which you usually must do to prevent the garbage collector re-arranging the heap). This is probably the most common usage. Pinning arrays on the heap can cause heap fragmentation, which hurts performance;
  3. As pointed out on a relevant stack overflow answer, stack memory is local to each thread, whereas the heap is shared. Creating arrays in this manner (typically in multi-threaded applications) can sometimes (especially in the case of allocating lots of arrays of ‘random’ sizes) mean that the heap is again fragmented, degrading performance.

As for the lack of performance upgrade, I have no answer. It may be that the CLR’s heap memory management is very good anyway, and therefore little difference is seen. Alternatively, the code I wrote above may be eliciting certain optimizations from the compiler or runtime that I haven’t thought of.

5: You can call instance methods as though they were static if they don’t reference any instance members

The best way to explain this one is with an example.

Take the following class:

public class ConsoleGreeter {
	public String Username;

	public void SayHello() {
		Console.WriteLine("Hello!");
	}

	public void GreetUser() {
		Console.WriteLine("Welcome, " + Username + "!");
	}
}

Pretty simple so far. Now, what do you expect to happen in the following example, assuming cg is null?

public static void CallSayHello(ConsoleGreeter cg) {
	cg.SayHello();
}

Obviously, we expect a NullReferenceException. But now ask yourself why we get such an exception. The reason is that that is a rule of the language (and the CLR): You can not call instance methods on a null reference.

But if such a rule didn’t exist, what would you expect to happen in the example above? The IL for SayHello() has already been defined. It does not actually reference the instance that you call it from at any point. So… If the rules were different… We could “legitimately” call SayHello() with a null reference. And it just so happens that there is a way to bend those rules with C# using the Reflection.Emit namespace.

The following paragraph is a technical explanation of what I’m about to show. If you just want to see the example, feel free to skip ahead.

MSIL (the interim assembly-like code that gets generated when you compile C# code) has two instructions for calling methods:

  • CALL
  • CALLVIRT

The first (call) is used to call static methods. The second (callvirt) is used to call instance methods. The nomenclature is slightly confusing here; because you could (justifiably) assume that callvirt would only be used when invoking virtual (overridable) methods. However, it is used for all instance methods, whether or not they are virtual. The reason for this is that call does not perform a null check on the first parameter passed on the stack (e.g. the object reference, if used with an instance method), and the CLR team decided that that check should always be made.

Using the IL Emitter, we can recreate the CallSayHello() and bypass the null reference check! Here’s an example I made:

public static DynamicMethod GetUnsafeInvocationMethod() {
	DynamicMethod callSayHelloMethod = new DynamicMethod(String.Empty, null, new[] { typeof(ConsoleGreeter) });

	ILGenerator ilGenerator = callSayHelloMethod.GetILGenerator();
	ilGenerator.Emit(OpCodes.Ldarg_0);
	ilGenerator.Emit(OpCodes.Call, typeof(ConsoleGreeter).GetMethod("SayHello"));
	ilGenerator.Emit(OpCodes.Ret);

	return callSayHelloMethod;
}

(You’ll notice I called this “GetUnsafeInvocationMethod“. Well, truthfully, there’s no real danger here. But it could produce results that no developer expects. So I chose to label it as unsafe.)

Now, we can call the DynamicMethod like so:

public static void Go() {
	ConsoleGreeter cg = null;

	DynamicMethod unsafeInvocation = GetUnsafeInvocationMethod();
	unsafeInvocation.Invoke(null, new[] { cg });
}

That is essentially the same as calling CallSayHello(null), except that the CLR will not perform a null reference check on the cg parameter when we try to use it to call SayHello(). The result is that we see “Hello!” on the console, despite never having a ConsoleGreeter to call the method with!

For your peace of mind, if you try to call GreetUser() (the other method of ConsoleGreeter) you’ll still get a null pointer exception, because it needs the Username instance field; which in turn requires an object reference.

As an interesting observation; call is slightly faster than callvirt.

6: You can control the addition and removal of delegates from your events

Consider the following example:

public static event Action SomethingHappened;

public static void RegisterEvent() {
	SomethingHappened += () => Console.WriteLine("Something happened!");
	SomethingHappened += () => Console.WriteLine("Something happened here too!");
	Action a = () => Console.WriteLine("A");
	Action b = () => Console.WriteLine("B");
	SomethingHappened += a;
	SomethingHappened += b;
}

public static void Go() {
	RegisterEvent();
	SomethingHappened();
}

I think pretty much any C# developer knows what will happen here. All four lines (“Something happened!” etc.) will appear on the console. However, maybe what you might not know is that you can explicitly control the addition and removal of those delegates to provide custom behaviour. An example is the best way to demonstrate:

private static event Action _somethingHappened;
public static event Action SomethingHappened {
	add { _somethingHappened = value; }
	remove {
		if (value == _somethingHappened) _somethingHappened = null;
	}
}

public static void RegisterEvent() {
	SomethingHappened += () => Console.WriteLine("Something happened!");
	SomethingHappened += () => Console.WriteLine("Something happened here too!");
	Action a = () => Console.WriteLine("A");
	Action b = () => Console.WriteLine("B");
	SomethingHappened += a;
	SomethingHappened += b;
}

public static void Go() {
	RegisterEvent();
	_somethingHappened();
}

So, what’s happened here? Well, first of all, we’ve renamed the event from SomethingHappened to _somethingHappened and accordingly its visibility has been reduced from public to private.
The next step is that we’ve declared a public event accessor set, referenced as SomethingHappened. Now, when external code (i.e. RegisterEvent()) adds and removes delegates from our event, we can control those external accesses. In this (contrived) example, I’ve replaced the delegate chaining mechanism, essentially restricting the event to a single delegate. The result is that the same code from before will now only print “B” on the console.

Although my example above is admittedly bad form (after all, you’re essentially overloading the meaning of ‘+=’ if you do this), there is a real use for this sort of construct: You can synchronize access to your events in multi-threaded code, like this:

private static readonly Object stateLock = new object();
private static event Action _somethingHappened;
public static event Action SomethingHappened {
	add {
		lock (stateLock) {
			_somethingHappened += value;
		}
	}
	remove {
		lock (stateLock) {
			_somethingHappened -= value;
		}
	}
}

This can be useful if you envisage delegates being added or removed from SomethingHappened at the same time as it and its chained delegates are being invoked.

7: You can instantiate interfaces (sort of)

For a lot of the examples so far you could be forgiven for shouting at me for even showing them; but this next one is really evil… Please don’t try it in production code :)Anyway, when is an interface not an interface? When it can be instantiated! Need an example? Well… Here you go:

public static unsafe void Go() {
	IMessageWriter messageWriter = new IMessageWriter();
	messageWriter.WriteHello();
}

I assure you that IMessageWriter is an interface, and that code compiles and runs. It even prints “Hello” on the console. So… What’s the trick? Well, here’s the full source code to make it work:

[ComImport]
[Guid("550e8400-e29b-41d4-a716-446655450000")]
[CoClass(typeof(ConsoleWriter))]
public interface IMessageWriter {
	void WriteHello();
}

public class ConsoleWriter : IMessageWriter {
	public void WriteHello() {
		Console.WriteLine("Hello");
	}
}

public static unsafe void Go() {
	IMessageWriter messageWriter = new IMessageWriter();
	messageWriter.WriteHello();
}

In essence, I’m abusing some special compilation magic that has been put in to MS’s C# compiler to aid programming with COM interfaces. I’ve had to import a fake COM interface (with a made up GUID) and then label my interface with [CoClass], specifying its default implementation as a ConsoleWriter. This behaviour is not part of any standard, so it’s not guaranteed to work with any other compiler (e.g. Mono) or even in future versions of MS’s compiler.

When I first saw it I thought it was ‘pretty cool’, and could be useful. But even if you ignore the fact that it’s the abuse of a compiler trick, all it could really be used for is a lame excuse for dependency injection.

8: You can make strings mutable with unsafe code

In case you didn’t know, strings in C# are immutable (they can’t be changed). In 99% of cases this is a really good thing (follow the link in the previous sentence to see some reasons why). However, it does involve a lot of copying and putting data on the managed heap- all of which adds memory pressure and eventually invokes the garbage collector.

So here’s an example of how you can modify strings but avoid creating a new String object (and garbaging the old one). This example is attributed to Wesner Moise’s ‘Strings UNDOCUMENTED‘ article.

/// <summary>
/// Mutates the target string, converting all characters to their upper-case variants.
/// </summary>
/// <param name="this">The extended string.</param>
public static unsafe void MutateToUpper(this string @this) {
	if (@this == null) throw new NullReferenceException("MutateToUpper called on a null string.");

	fixed (char* fixedCharacterArray = @this) {
		for (char* character = fixedCharacterArray; *character != 0; character++) {
			*character = char.ToUpper(*character);
		}
	}
}

This extension method will mutate a string ‘in-situ’, altering its value without creating a new string. The method obtains a pointer to the first character of the string, and then iterates through each character, replacing it with its upper-case counterpart, until the NULL character is reached (which the CLI guarantees all strings will end with). Here’s an example of its usage:

public static unsafe void Go() {
	String first = "Hello";
	first = first.ToUpper();

	String second = "Hello";
	second.MutateToUpper();

	Console.WriteLine(first);
	Console.WriteLine(second);
}

An important note: I disabled string interning explicitly before testing this (although as far as I know it’s disabled by default these days anyway).

The result of the code above is that I see “HELLO” printed twice on the console. The second time, I never added any extra memory usage.

9: You can prevent people from using ILDASM to inspect your code

Eventually, of course, all attempts to protect your IP are futile; determined hackers/engineers will probably get at your juicy creativity one way or another! But one of the first steps you can take is to prevent people using the popular IL disassembler tool to investigate your assemblies.

Here’s a screenshot of the assembly I’ve been using to test the code in this blog disassembled:

ildasm

Now… By adding a single line, and recompiling, I can try that again and see this:

ildasmDenied

You can do this by adding the assembly attribute SuppressIldasm. Be warned that this won’t prevent reflection-like tools from perusing your libraries. But it’s one extra step that’s possibly worth taking if you’re going to try and protect your IP.

An example follows. The relevant line has been highlighted.

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CSharpAdvancedTricks")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CSharpAdvancedTricks")]
[assembly: AssemblyCopyright("Copyright ©  2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: SuppressIldasm]

10: You can create your own awaitable objects

I first read about this functionality in the brilliant book CLR via C# by Jeffrey Richter. The following example is attributed to him, and if you like it, I suggest you buy his book! This example is left ’til last because it’s a big one. So get some tea if you need to. :)

As you may already know, it’s possible to ‘await‘ any Task in C#, as long as you do so in a method marked as ‘async‘:

public static async Task Go() {
	double calcResult = await GetBigCalculation();
	Console.WriteLine("Calculation result is: " + calcResult);
}

public static Task<double> GetBigCalculation() {
	return Task.Run(() => {
		double result = 0f;
		for (int i = 0; i < 100000; ++i) {
			result = Math.Sqrt(result + i);
		}
		return result;
	});
}

Basically, once the runtime hits the highlighted line above, the control will be returned to the caller of Go(), effectively turning the method in to a state machine (actually, it was already a state machine once it was compiled… But that’s for another day).

But what you might not have known is that you can actually await any object that simply defines a GetAwaiter() method!

What does this mean, I hear you ask? Well, it means you can get the beauty of C#5′s async/await operations for your own custom items. The best way to demonstrate this is with an example (which I borrowed from Jeffery Richter): An event awaiter!

The event awaiter

We will now build a small class that will let us await an event. In much the same way that the example above awaited the Task returned by GetBigCalculation, this class will let us await for an event to be fired, providing semantics similar to waiting for an I/O operation or long computation.

Step 1: Provide a matching delegate

The first step, actually, is to create our class. So here we go:

public class EventAwaiter : INotifyCompletion {

}

I’ve created a class called EventAwaiter that also implements INotifyCompletion. The MSDN summary for this interface tells us that objects who implement INotifyCompletionrepresent an operation that schedules continuations when it completes“. We are implementing this interface in order to allow the async/await state machine to tell us what to call once an event is raised. Here is how:

public class EventAwaiter : INotifyCompletion {
	private Action eventFiredContinuation = null;

	public void OnCompleted(Action continuation) {
		eventFiredContinuation = continuation;
	}
}

INotifyCompletion declares only one method: OnCompleted(). When someone uses our new EventAwaiter, the state machine will call OnCompleted() and give us an action for us to call when our event is fired.
So, simply put, when our awaited event is fired, we simply call eventFiredContinuation and the state machine will take care of the rest for us!

So, how do we know when the event has been raised? Well, this is a two-step process. Firstly, we need to define a method that matches the delegate prototype of the event we wish to wait for. However, not all events accept the same delegate type. So for now, I’m going to add a type that conforms for any events that expect an EventHandler delegate:

public class EventAwaiter<TEventArgs> : INotifyCompletion {
	private Action eventFiredContinuation = null;

	public void OnCompleted(Action continuation) {
		eventFiredContinuation = continuation;
	}

	public void EventRaised(object sender, TEventArgs eventArgs) {

	}
}

Now, our EventAwaiter users can add the awaiter to an event like so:

static void Go() {
	var eventAwaiter = new EventAwaiter<FirstChanceExceptionEventArgs>();
	AppDomain.CurrentDomain.FirstChanceException += eventAwaiter.EventRaised;
}

And if, in the future, we wish to provide support for different delegate types, we can maybe change the way our EventAwaiter works, perhaps allowing it to be extended. For now though, let’s move on…

Step 2: Hook it all up

So, now, we just need to hook it all up! Our method EventRaised will be called when the FirstChanceException is raised. So, what do we do inside it? Simple! We call the continuation action that was given to us by the state machine!

public class EventAwaiter<TEventArgs> : INotifyCompletion {
	private Action eventFiredContinuation = null;

	public void OnCompleted(Action continuation) {
		eventFiredContinuation = continuation;
	}

	public void EventRaised(object sender, TEventArgs eventArgs) {
		if (eventFiredContinuation != null) eventFiredContinuation();
	}
}

We’ve only added one more line (highlighted). We simply check if the eventFiredContinuation is null, and then fire it off; which will then relinquish control back to the state machine. You may wonder why we check for null. Well, it’s possible that the event is fired (and EventRaised() is called) before the state machine gives us our continuation.

There is one final piece to this puzzle, however. Eventually, when the awaited result is returned back to the caller, the state machine will call a method GetResult() in order to provide the result (in this case, our FirstChanceExceptionEventArgs). So… Let’s add this method, and everything we might need to facilitate it:

public class EventAwaiter<TEventArgs> : INotifyCompletion {
	private Action eventFiredContinuation = null;
	private TEventArgs eventArgs;

	public void OnCompleted(Action continuation) {
		eventFiredContinuation = continuation;
	}

	public TEventArgs GetResult() {
		return eventArgs;
	}

	public void EventRaised(object sender, TEventArgs eventArgs) {
		this.eventArgs = eventArgs;
		if (eventFiredContinuation != null) eventFiredContinuation();
	}
}

(All the lines we added have been highlighted)

So, now, when EventRaised() is called, we set the private field eventArgs to the event args that were passed from the raised event. Then, we call eventFiredContinuation() to allow the state machine to continue. Finally, the state machine calls GetResult(), and the eventArgs are returned, and given to the awaiter, like this:

static async void Go() {
	var eventAwaiter = new EventAwaiter<FirstChanceExceptionEventArgs>();
	AppDomain.CurrentDomain.FirstChanceException += eventAwaiter.EventRaised;

	var eventArgs = await eventAwaiter;
}

Step 3: Make the EventAwaiter awaitable

Finally, in order to allow us to actually use the code above, and await the EventAwaiter, we need to add the method I mentioned right at the beginning: GetAwaiter():

public class EventAwaiter<TEventArgs> : INotifyCompletion {
	private Action eventFiredContinuation = null;
	private TEventArgs eventArgs;

	public void OnCompleted(Action continuation) {
		eventFiredContinuation = continuation;
	}

	public TEventArgs GetResult() {
		return eventArgs;
	}

	public void EventRaised(object sender, TEventArgs eventArgs) {
		this.eventArgs = eventArgs;
		if (eventFiredContinuation != null) eventFiredContinuation();
	}

	public EventAwaiter<TEventArgs> GetAwaiter() {
		return this;
	}
	public bool IsCompleted { get { return eventArgs != null;  } }
}

The GetAwaiter() method returns the EventAwaiter itself. You may also notice that I’ve added a public boolean property IsCompleted, the state machine needs this to check whether or not you’re ready to return a result to the awaiter.

In its current state, everything compiles; but there are two problems: Firstly, it’s not thread safe (and it should always be, as we’re creating an async/await override), and secondly it will only reliably work for the first time an event is fired. Therefore, there’s one last step to do, and then we have our awaiter!

Step 4: Make it thread safe, and re-usable

Below is the completed EventAwaiter. There are no logical changes to what you’ve already seen; only a few changes to make it thread safe and re-usable (which I’ve highlighted).

/// <summary>
/// Allows a user to 'await' an event to be fired.
/// </summary>
public class EventAwaiter<TEventArgs> : INotifyCompletion {
	private Action eventFiredContinuation = null;
	private ConcurrentQueue<TEventArgs> queuedEventArgs = new ConcurrentQueue<TEventArgs>();

	public void OnCompleted(Action continuation) {
		Volatile.Write(ref eventFiredContinuation, continuation);
	}

	public TEventArgs GetResult() {
		TEventArgs latestArgs;
		queuedEventArgs.TryDequeue(out latestArgs);
		return latestArgs;
	}

	public void EventRaised(object sender, TEventArgs eventArgs) {
		queuedEventArgs.Enqueue(eventArgs);
		Action continuation = Interlocked.Exchange(ref eventFiredContinuation, null);
		if (continuation != null) continuation();
	}

	public EventAwaiter<TEventArgs> GetAwaiter() {
		return this;
	}
	public bool IsCompleted { get { return queuedEventArgs.Count > 0;  } }
}

The first, and most noticeable change is that I’ve replaced the eventArgs field with a ConcurrentQueue of TEventArgs. This allows us to await the same event multiple times, and even lets us handles scenarios where the event is triggered multiple times before the state machine gets a change to call IsCompleted. Every time EventRaised() is called, we add the event args to the queue, and then those event args are pulled off the queue one-at-a-time, each time GetResult() is called.

The other changes are to do with thread-safety. The eventFiredContinuation has a write barrier applied, so that when we check if it’s null later on (in EventRaised), we don’t get a cached/stale value.

Finally, on each call to EventRaised, we get the value of eventFiredContinuation and exchange its value with null. This is because only one thread must call the continuation. (The state machine will pass a new continuation to OnCompleted shortly after).

Finally, it’s done! We can now use the EventAwaiter like this:

static async void Go() {
	var eventAwaiter = new EventAwaiter<FirstChanceExceptionEventArgs>();
	AppDomain.CurrentDomain.FirstChanceException += eventAwaiter.EventRaised;

	while (true) {
		var eventArgs = await eventAwaiter;
		Console.WriteLine("A " + eventArgs.Exception.GetType().Name + " exception was thrown! Message: " + eventArgs.Exception.Message);
	}
}

Pretty cool, huh?

About these ads

11 thoughts on “10 Things You Maybe Didn’t Know About C#

  1. There are a couple of problems with your benchmark for #4 (stackalloc). You’re only looking at 10,000 element arrays, and your benchmark that fills the arrays takes much longer than the allocation itself. So in a way you’re not really comparing stack vs. heap allocations, you’re comparing the time it takes to calculate powers and store them into memory.

    I’ve modified your benchmark a little and it then shows very clearly that for large arrays (allocated on the LOH), there is a considerable performance difference in stack vs. heap allocations: http://blogs.microsoft.co.il/blogs/sasha/archive/2013/10/17/on-stackalloc-performance-and-the-large-object-heap.aspx

  2. Pingback: Debug the debugger | Windows Live space
  3. I think probably nobody had any need to try out your first tip, because I think it must contain an error. With any of the .NET frameworks available to me (2.0, 3.0, 3.5, 4.0, and 4.5 — all from Mono), I can not avoid a compile-time error when attempting to cast an Array to (string[]). The only way I could see this cast happening is to .Copy() or .Clone() the Array.

    You can see a slightly modified version of the code here. The inclusion of anonymous functions does not change anything (I tested without them, as well).

    If that exception is thrown (and caught) then the casting is not allowed.

    I’m using some anonymous WordPress account because I do not have (nor do I want) one.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s