tricks - Hidden Features of C#?




tips and tricks for c# code optimization (20)

This came to my mind after I learned the following from this question :

where T : struct

We, C# developers, all know the basics of C#. I mean declarations, conditionals, loops, operators, etc.

Some of us even mastered the stuff like Generics , anonymous types , lambdas , LINQ , ...

But what are the most hidden features or tricks of C# that even C# fans, addicts, experts barely know?

Here are the revealed features so far:


Keywords

Attributes

Syntax

Language Features

Visual Studio Features

Framework

Methods and Properties

Tips & Tricks

Other

https://code.i-harness.com


From CLR via C# :

When normalizing strings, it is highly recommended that you use ToUpperInvariant instead of ToLowerInvariant because Microsoft has optimized the code for performing uppercase comparisons .

I remember one time my coworker always changed strings to uppercase before comparing. I've always wondered why he does that because I feel it's more "natural" to convert to lowercase first. After reading the book now I know why.


Not sure why anyone would ever want to use Nullable<bool> though. :-)

True, False, FileNotFound ?


  1. ?? - coalescing operator
  2. using ( statement / directive ) - great keyword that can be used for more than just calling Dispose
  3. readonly - should be used more
  4. netmodules - too bad there's no support in Visual Studio

" yield " would come to my mind. Some of the attributes like [DefaultValue()] are also among my favorites.

The " var " keyword is a bit more known, but that you can use it in .NET 2.0 applications as well (as long as you use the .NET 3.5 compiler and set it to output 2.0 code) does not seem to be known very well.

Edit: kokos, thanks for pointing out the ?? operator, that's indeed really useful. Since it's a bit hard to google for it (as ?? is just ignored), here is the MSDN documentation page for that operator: ?? Operator (C# Reference)


Aliased generics:

using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;

It allows you to use ASimpleName , instead of Dictionary<string, Dictionary<string, List<string>>> .

Use it when you would use the same generic big long complex thing in a lot of places.



From Rick Strahl :

You can chain the ?? operator so that you can do a bunch of null comparisons.

string result = value1 ?? value2 ?? value3 ?? String.Empty;

Here are some interesting hidden C# features, in the form of undocumented C# keywords:

__makeref

__reftype

__refvalue

__arglist

These are undocumented C# keywords (even Visual Studio recognizes them!) that were added to for a more efficient boxing/unboxing prior to generics. They work in coordination with the System.TypedReference struct.

There's also __arglist, which is used for variable length parameter lists.

One thing folks don't know much about is System.WeakReference -- a very useful class that keeps track of an object but still allows the garbage collector to collect it.

The most useful "hidden" feature would be the yield return keyword. It's not really hidden, but a lot of folks don't know about it. LINQ is built atop this; it allows for delay-executed queries by generating a state machine under the hood. Raymond Chen recently posted about the internal, gritty details .


I didn't know the "as" keyword for quite a while.

MyClass myObject = (MyClass) obj;

vs

MyClass myObject = obj as MyClass;

The second will return null if obj isn't a MyClass, rather than throw a class cast exception.


I tend to find that most C# developers don't know about 'nullable' types. Basically, primitives that can have a null value.

double? num1 = null; 
double num2 = num1 ?? -100;

Set a nullable double, num1 , to null, then set a regular double, num2 , to num1 or -100 if num1 was null.

http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx

one more thing about Nullable type:

DateTime? tmp = new DateTime();
tmp = null;
return tmp.ToString();

it is return String.Empty. Check this link for more details


If you want to exit your program without calling any finally blocks or finalizers use FailFast :

Environment.FailFast()

If you're trying to use curly brackets inside a String.Format expression...

int foo = 3;
string bar = "blind mice";
String.Format("{{I am in brackets!}} {0} {1}", foo, bar);
//Outputs "{I am in brackets!} 3 blind mice"

Mixins. Basically, if you want to add a feature to several classes, but cannot use one base class for all of them, get each class to implement an interface (with no members). Then, write an extension method for the interface , i.e.

public static DeepCopy(this IPrototype p) { ... }

Of course, some clarity is sacrificed. But it works!


My favorite trick is using the null coalesce operator and parentheses to automagically instantiate collections for me.

private IList<Foo> _foo;

public IList<Foo> ListOfFoo 
    { get { return _foo ?? (_foo = new List<Foo>()); } }

The 'default' keyword in generic types:

T t = default(T);

results in a 'null' if T is a reference type, and 0 if it is an int, false if it is a boolean, etcetera.


This isn't C# per se, but I haven't seen anyone who really uses System.IO.Path.Combine() to the extent that they should. In fact, the whole Path class is really useful, but no one uses it!

I'm willing to bet that every production app has the following code, even though it shouldn't:

string path = dir + "\\" + fileName;

Two things I like are Automatic properties so you can collapse your code down even further:

private string _name;
public string Name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
    }
}

becomes

public string Name { get; set;}

Also object initializers:

Employee emp = new Employee();
emp.Name = "John Smith";
emp.StartDate = DateTime.Now();

becomes

Employee emp = new Employee {Name="John Smith", StartDate=DateTime.Now()}

Using @ for variable names that are keywords.

var @object = new object();
var @string = "";
var @if = IpsoFacto(); 

Unions (the C++ shared memory kind) in pure, safe C#

Without resorting to unsafe mode and pointers, you can have class members share memory space in a class/struct. Given the following class:

[StructLayout(LayoutKind.Explicit)]
public class A
{
    [FieldOffset(0)]
    public byte One;

    [FieldOffset(1)]
    public byte Two;

    [FieldOffset(2)]
    public byte Three;

    [FieldOffset(3)]
    public byte Four;

    [FieldOffset(0)]
    public int Int32;
}

You can modify the values of the byte fields by manipulating the Int32 field and vice-versa. For example, this program:

    static void Main(string[] args)
    {
        A a = new A { Int32 = int.MaxValue };

        Console.WriteLine(a.Int32);
        Console.WriteLine("{0:X} {1:X} {2:X} {3:X}", a.One, a.Two, a.Three, a.Four);

        a.Four = 0;
        a.Three = 0;
        Console.WriteLine(a.Int32);
    }

Outputs this:

2147483647
FF FF FF 7F
65535

just add using System.Runtime.InteropServices;


lambdas and type inference are underrated. Lambdas can have multiple statements and they double as a compatible delegate object automatically (just make sure the signature match) as in:

Console.CancelKeyPress +=
    (sender, e) => {
        Console.WriteLine("CTRL+C detected!\n");
        e.Cancel = true;
    };

Note that I don't have a new CancellationEventHandler nor do I have to specify types of sender and e , they're inferable from the event. Which is why this is less cumbersome to writing the whole delegate (blah blah) which also requires you to specify types of parameters.

Lambdas don't need to return anything and type inference is extremely powerful in context like this.

And BTW, you can always return Lambdas that make Lambdas in the functional programming sense. For example, here's a lambda that makes a lambda that handles a Button.Click event:

Func<int, int, EventHandler> makeHandler =
    (dx, dy) => (sender, e) => {
        var btn = (Button) sender;
        btn.Top += dy;
        btn.Left += dx;
    };

btnUp.Click += makeHandler(0, -1);
btnDown.Click += makeHandler(0, 1);
btnLeft.Click += makeHandler(-1, 0);
btnRight.Click += makeHandler(1, 0);

Note the chaining: (dx, dy) => (sender, e) =>

Now that's why I'm happy to have taken the functional programming class :-)

Other than the pointers in C, I think it's the other fundamental thing you should learn :-)







hidden-features