I’ve been doing a series of tweets with the somewhat misleading name “Things I did not know about C#” for a while, where I’ve written shortly about features and behaviours in C#. Either ones that
- I’ve stumbled upon
- found interesting
- I knew existed but I’ve never used
- I have not fully understood how they work under the hood
I thought I should gather the first five “lessons” in a blog post. This also gives me some more space to add context and explanation to the examples than can be fitted into a tweet.
Some of these features doesn’t really make sense and you really need to wedge in an use case where they would make
sense. But after all, these are things I did not know about C# - not necessarily useful things!
#1: Passing objects of different types into the same collection
I’ve created an empty interface, IMyPrettyInterface. The classes TypeA and TypeB are simple POCO classes, consisting of two properties each. Both of the classes implements IMyPrettyInterface.
Normally it wouldn’t be possible to pass instances of these two classes into a generic collection. The other option would’ve been to initialize a list of type object.
But by declaring a list of an interface, you can add any object that implements said interface to the collection.
#2: Tuples allows you to have multiple return values from a method
Having been introduced in C# 7.0, tuples is a fairly new feature to the C# language. Tuples fills its main purpose when you want to have more than one return value from a method, but you don’t want the overhead of creating a DTO class just for this one specific usage.
There’s been other ways of solving this issue before, but with tuples you get a really clean and easy to read solution that is also compatible with async methods.
#3: The yield keyword
The yield keyword allows you rather than returning a collection, return a promise of an collection.
Below is a small app that prints the numbers 1-5. When stepping through this code (using F11 in Visual Studio), you’ll see that the cursor will skip the first line in the method GetNumbersYield after the first iteration. Instead it will move on to the while, verify if the condition has been met or not and then return an integer if the condition has been met.
If we instead look at the example below, we’ve returned a list of integers instead of using yield. These two examples does the same thing, but in this second example we initialize a list and populate it with the numbers 1-5. Thereafter the whole list is returned, looped through and printed. As opposed to the yield solution, a collection must be initialized and kept in memory.
The community is in a divide about about this one, but in my environment (without using fancy performance
analyzers) the yield approach is about 50% faster than the “classic” approach when I’ve done some testing
#4: The dynamic keyword
Dynamic typed variables in C#?! Isn’t static typing one of the main benefits of using C#? But before you bring out your garlic, crucifixes and wooden stakes, read this through:
But wait a minute - why not use the var keyword? What is the difference?
Answer: variables declared using ‘var’ get their data type set at compile time and doesn’t allow changes to the data type held within.
So what can you use this for? After reading up on the subject on forums and blogs, I find that the general opinion in the community seems to be to avoid using dynamics in C# unless absolutely needed.
By using dynamics you lose intellisense and the safety net that comes with static typing (e g your IDE pointing out conversion errors at compile time, when trying to assign values of incorrect data types to object properties etc).
An example displaying one downside of dynamics:
A scenario when dynamics could come in handy would be when you’re expecting an object as return value, but you’re not sure of what type that object is going to be. You also might want to manipulate one or more of the object’s properties.
#5: The volatile keyword
When working multithreaded, you can help reducing concurrency issues by using the volatile keyword. Be aware that this is not a foolproof fix, but it can help minimizing the risk of certain issues common in multithreaded apps. It’s still a very good idea to use the lock statement.
Example: your app is using two concurrent threads that accesses the same variable. Thread 1 makes a change to the variable’s value and the change is saved in thread 1’s cache. But before the change is saved to main memory, thread 2 can still possibly get the outdated value of that variable from main memory.
By making a variable volatile, you explicitly say that “never cache this value, write/read the main memory directly”. The thread therefore gets the most up-to-date value. Worth pointing out is that all writes in C# are always volatile. It is in the reads that this behaviour might occur.
The compiler always tries to make performance optimizations where able. Using volatile makes the compiler skip these optimizations, and we get somewhat more predictable code.