Things in C# you might have missed

Posted by Filip Ekberg on September 18 2012 14 Comments

A while back I did a short programming quiz on my blog and a lot of you responded to each question with interesting ways to solve those puzzles. Here is a list with those questions among other interesting things that you might now have used in your day-to-day development.

Bits n’ Bytes

The more you know about the internals in the system you are working on, the greater your advantage is. Let’s focus on the bits and bytes for now. A bit is either a 1 or a 0 which represents value/no-value or on/off; a byte is a sequence of 8 bits.

Take a look at these three tables:

As you might see this is a base-2 representation. It starts at 1, then 2, then 4 and so forth to how far you’d like to go. For simplicity, the table only goes to 128. By letting some of them be 1s and some be 0s, you can represent any number you like.

Fun fact: the ASCII decimal value for the capital letter A is 65 which means the bit-representation would look like this: 01000001 if added to the above table!

Now when we do this, we can do something really powerful called bit-shifting. This means moving the bit N steps to either direction (left/right).

This takes us to the first question that I shouted out on twitter:

How can we multiply any given value by 2 without using any arithmetic operations?

The answer is simple, we use bit-shift! Below is an example of how we can do this.

int x = 10;
int result = x << 1;

The << means that we shift it to the left and the following value defines how many steps. Below is another table showing what changed, all bits were moved 1 step to the left.

There are lot of more interesting things you can do when knowing your bits n’ bytes, such as logical and/or.

A number, but not really

Almost 3 years ago I answered a question on StackOverflow where the question was the following:

Suppose you have this loop definition:
while (i == i) ;

What is the type of i and the value of i if the loop is not an infinite loop and the program is using only one thread?

Let us assume that this is built in types in .NET and that we are not allowed to override the equality operators. This makes it pretty hard to figure out, right?

This introduces NaN — Not a Number. But how can it be a number but not a number at the same time? NaN was introduced because of imaginary numbers such as

Sqrt(-1)

So, let us try to get the square root of -1 in C#:

var result = Math.Sqrt(-1);
Console.WriteLine(result == result);

Can you guess what this prints?

It actually prints false! This is because NaN == NaN will always return false! Because comparing something that is not correct with something else that is not correct doesn’t make any sense.

But what type is it?

We know that Math.Sqrt returns a double. So the answer is Double.NaN.

Cleaner code without temporary lists

Do you find yourself having tons of methods that contain temporary lists that you want to return in the end of the method?

For simplicity I’m going to use a method in the following example that I would normally just use LINQ to achieve.

Here I have a method that just check is a list of names contain my pattern:

IEnumerable<string> _names = new[] {"Filip", "Sofie"};
IEnumerable<string> GetList(string pattern)
{
    var found = new List<string>();

    foreach(var name in _names)
    {
        if(name.Contains(pattern))
        {
            found.Add(name);
        }
    }

    return found;
}

It’s not really that messy, but it can be cleaned up. If we have a lot of methods like this, we can make the code base much easier to read through. What we can do is to make use of the yield keyword like this:

IEnumerable<string> _names = new[] {"Filip", "Sofie"};
IEnumerable<string> GetList(string pattern)
{
    foreach(var name in _names)
    {
        if(name.Contains(pattern))
        {
            yield return name;
        }
    }
}

Why are there uppercase and lowercase versions of object/string etc?

object, string, int, double and the other value types are just keyword aliases for their representations in System.*.

For example, object is really System.Object, string is System.String and int is System.Int32.

When the code is compiled, it doesn’t matter if you wrote string or System.String, it’s going to be the same IL!

Vote on HN

14 Responses to Things in C# you might have missed

  1. Anders HolmströmNo Gravatar says:

    A bunch of nice tricks!

    The yield thing is interesting to me. I usually compose methods with yield just like you propose, and I also think it makes code cleaner and easier to read. But, really, isn’t it just a ‘magical word’ that makes something happen without it being really clear unless you know exactly what the keyword does?

    Now, one could argue that this goes for all syntax in e.g. C#, but I think some of the fancier keywords can introduce complexity. E.g. what can a future coder reading your code be expected to grok and what is better to write out in a very obvious, imperative way for clarity’s sake?

    The same argument I think can be made for over-using lambda syntax (something which I also use whenever possible). Yes, it’s very expressive and succint code, but is it harder or easier to grasp than a cleanly written delegate passed in by name?

    Should code be “dumbed down” in order to cater to a wider developer audience, or should developers be expected to be fluent with things like yield, await etc? I don’t think a clear answer exists, but I find this question popping up in my head every now and then.

  2. Pingback: Dew Drop – September 19, 2012 (#1,404) | Alvin Ashcraft's Morning Dew

  3. Paul MarfleetNo Gravatar says:

    You could use LINQ to express this code more succinctly:

    IEnumerable<string> _names = new[] {"Filip", "Sofie"};
    IEnumerable<string> GetList(string pattern)
    {
       return _names.Where(name => name.Contains(pattern));
    }
  4. Paul MarfleetNo Gravatar says:

    @Anders

    The explicit use of yield isn’t actually necessary here. The code could be expressed more succinctly with LINQ, using the Enumerable.Where extension method. It’s also worth pointing out that the use of an iterator block in the ‘cleaned up’ code sample does introduce a subtle but important difference in the way the two methods behave, namely that of deferred execution. The original code will be executed eagerly, with the results returned immediately to the calling code as a materialized list. The ‘cleaned up’ code however will be executed lazily; the iterator will only yield items as the Enumerable is enumerated. The C# compiler generates a state machine behind the scenes to handle this, so the iterator can keep track of its state as more items are yielded to the caller. Deferred execution means that a generator for an infinite sequence can be defined; something that wasn’t possible with the original example where the entire list had to be materialized in memory before being returned to the caller.

  5. Filip EkbergNo Gravatar says:

    Thank you for your comments.

    Paul, I agree with you. Normally I wouldn’t do the method like that, but use LINQ instead, it was just a good way to show the difference between a temporary list and using yield; without it having to be a very complex and large example.

    In the post I do say that I wouldn’t normally do this because I would use LINQ (for that code sample that is.)

    For simplicity I’m going to use a method in the following example that I would normally just use LINQ to achieve.

    There is indeed a big difference in the IL generated from the two samples. The IL generated is a bit lengthy, so I put it up in a gist here: https://gist.github.com/3751194

    Anders, we discussed this on twitter a bit and I think it’s an interesting point of view. I think that as long as the “magical keyword” is well-known to those working on the system, there is no problem. As long as it makes the code less complex.

    If the code is too complex after a refactoring, you need to re-do the refactoring!

  6. Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1193

  7. Richard SmithNo Gravatar says:

    There’s a slightly more interesting use of yield to replace your generation of _names:

    IEnumerable<string> _names
    {
      get
      {
        yield return "Filip";
        yield return "Sofie";
      }
    }

    This gets really useful when testing code against IEnumerables of more complex types that would otherwise be built up from databases and the like.

  8. Michael LundNo Gravatar says:

    You should never use bitshift to multiply by two, four, eight etc. That is old school C and assembelr style multiplication.
    All moderne compilers should automatically recognice when you multiply by a power of two and internally use bitshift in the assembler (in the case of C# this might happen, when converting to IL or when the jitter translates IL to assembler)

    There is no reason to make the code harder to read than strictly necessary.

    The bitshift operators do have their uses when doing real bit arithmetic or for instance creating a 32bit int from four bytes: (byte1 << 24) + (byte2 << 16) + (byte3<<8) + byte4

  9. tatabánya angolNo Gravatar says:

    @Richard: yep, yield is an underestimated word in .NET.

  10. esskarNo Gravatar says:

    But yield can also be dangerous because the code is not executed unless the enumerations is evaluated.

  11. Pingback: Cheatsheet: 2012 09.12 ~ 09.23 - gOODiDEA.NET

  12. TobiasNo Gravatar says:

    I love the yield operator and use it where possible. Another advantage of IEnumerable return yield can lead to very effective code (both in composability, performance and memory pressure).

    Think of a big log reader which returns every line as string and you are only interested in working with a line containing a specific criteria. If you append every line to an List and then filter them out the memory pressure can get extremely high. Otherwise you have to implement the filter logic inside of the same logic (or add a delegate, but this inverses the logic which I find very ugly and makes it more complex to understand) and add only items that match the criteria. With yield you can be very composable and split the two tasks into different methods/components/assemblies and replace them with other implementations (e.g. read only every second line).
    Btw. if you read a big file line by line (like in my big log file example) use File.ReadLines() instead of File.ReadAllLines(), which in fact returns a IEnumerable.

    @esskar: that’s true, you have to be aware of this and cast it when necessary to a list or an array before using it multiple times. Because of this “problem” .NET 4.5 introduces IReadOnlyCollection and IReadOnlyList, which can be seen as hint, that the List is already materialized. This blog post talks about the new interfaces.

  13. Bob SnyderNo Gravatar says:

    Be careful alot of coding is readablity. I read about bit shifting and why to use it in an old graphics coding book because it’s faster than multiplying. In college I was writing a homework assignment for netowkring code, and I used bit shifting to muplty by 256. One problem I got it wrong because they didn’t understand what I was doing. I got partial credit eventual, but who wants to take the time to argue with the grader. So if your going to use this code in production make sure it’s heavliy commmented. Also, learn from me don’t use it in school assignments.

  14. Pingback: Using bit fields in C#

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>