Nooks and Crannies explores some interesting techniques and methods that are specific to a given language. While these techniques may not be useful in everyday development they could come in handy in niche application and scenarios. Word of warning though; the fact that these techniques could be considered obscure should warrant a second thought before they are included in production code.
Unions
A popular technique I used often when developing system communication modules in C; this allows us to reference the same section of memory as different formats. Commonly this is used to handle transitions between little-endian and big-endian systems or manipulate byte level data (for say IP address modeling).
While C# does not support the ‘union’ keyword like C/C++, you can gain similar functionality through the use of the structure layout attributes. Specifically we will be ‘explicitly’ setting the field offset of each structure member in order to be able to reference the same memory via different methods.
1 2 3 4 5 6 7 8 9 10 11 12 | [StructLayout(LayoutKind.Explicit)] public struct ExampleUnion { [FieldOffset(0)] public UInt16 getUI16; [FieldOffset(0)] public Byte getByte1; [FieldOffset(1)] public Byte getByte2; } |
The definition above allows us to access the same memory location as both an unsigned 16 bit integer or via 2 separate byte members.
1 2 3 4 5 6 | ExampleUnion test; test.getByte1= 0; // needed to make the compiler happy test.getByte2= 0; test.getUI16= 0xAABB; Console.WriteLine("{0:X}", test.getByte1); Console.WriteLine("{0:X}", test.getByte2); |
The above code will result into either:
BBAA
Or
AABB
Depending on the endian of the system it is executed on.
Non-Zero Based Arrays
The vast majority of the time in C# we use zero based arrays (in fact I can’t recall a time I haven’t used one in production code); but it is possible to define arrays that are not zero based. One thing to note; the non-zero based arrays are not CLS compliant. In order to create the array we have to use the ‘CreateInstance’ method. This method allows us to define the type, length, and lower bounds. We can set the lower bounds to something other than 0 and have our non-zero based array!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // Create the instance of an Array Array myArray = Array.CreateInstance(typeof(int), new[] { 4 }, new[] { 2011 }); // Set the values to array myArray.SetValue(5, 2005); myArray.SetValue(6, 2006); myArray.SetValue(7, 2007); myArray.SetValue(8, 2008); // Display the lower bound of the array Console.WriteLine(myArray.GetLowerBound(0)); // Display the upper bound of the array Console.WriteLine(myArray.GetUpperBound(0)); // Display all the items in the array for (int i = myArray.GetLowerBound(0); i <= myArray.GetUpperBound(0); i++) Console.WriteLine(myArray.GetValue(i)); |
Extend Enums
Coming from a C/C++ background enumerated values were simply a method to rename integer values for specific purposes. This is not the case in C#, where enum is actually a object! We can extend the object similar to a class to add additional functionality.
1 2 3 4 5 6 7 8 9 10 | public enum Grades { F = 0, D=1, C=2, B=3, A=4 }; // Define an extension method in a non-nested static class. public static class Extensions { public static Grades minPassing = Grades.D; public static bool Passing(this Grades grade) { return grade >= minPassing; } } |
We can invoke the methods by using the declared enum.
1 2 3 4 5 | static void Main(string[] args) { Grades g1 = Grades.A; Console.WriteLine("First {0} a passing grade.", g1.Passing() ? "is" : "is not"); } |
Private members can be accessed by other Class Instances
This is one you have probably actually used without realizing it. Sit back a moment and ponder if a private member should be accessible from a non-local instance of the class. I thought it could not, but after running a quick test I realized my mistake! A class of the same type can access the private members from within the class methods; this is great for performing deep comparisons of classes.
1 2 3 4 5 6 | class Privates { private int MyCount; public bool Equals(Privates PassedPrivates) { return PassedPrivates.MyCount == MyCount; } } |
??
No, that’s not a typo or a question. It is the C# null coalescing operator. This operator allows you to inspect an object to see if it is null and if so return the right hand operand. This is a great way to promote more readable code! For instance it turns this:
1 2 3 4 5 6 7 8 | If (amINull.Name == null) { Name = “No Name”; } Else { Name = amINull.Name; } |
to this:
1 | Name = amINull.Name ?? “No Name”; |
This can quickly reduce your code size and complexity once the knowledge percolates amongst your team!
Know any other C# intricacies? Please leave a comment so we can discuss them!
[edit]Thank you to Brian MacKay for pointing out corrections on Enums and the Null Coalescing sections![/edit]
Fun tricks. I know I make good use of the ?? operator. Really helps ensure your code is concise.
Fun little post. Non-zero based arrays seem like a great way to trip up people!
Hope you do some other languages too.
Private class member accessible by the same class makes sense but is also strange.
Sorta like someone else reaching into your pockets!