Hidden Features of C#?




tips and tricks for c# code optimization (24)

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

  • Nice method for event handlers by Andreas H.R. Nilsson
  • Uppercase comparisons by John
  • Access anonymous types without reflection by dp
  • A quick way to lazily instantiate collection properties by Will
  • JavaScript-like anonymous inline-functions by roosteronacid

Other


Returning anonymous types from a method and accessing members without reflection.

// Useful? probably not.
private void foo()
{
    var user = AnonCast(GetUserTuple(), new { Name = default(string), Badges = default(int) });
    Console.WriteLine("Name: {0} Badges: {1}", user.Name, user.Badges);
}

object GetUserTuple()
{
    return new { Name = "dp", Badges = 5 };
}    

// Using the magic of Type Inference...
static T AnonCast<T>(object obj, T t)
{
   return (T) obj;
}

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>()); } }

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.


This one is not "hidden" so much as it is misnamed.

A lot of attention is paid to the algorithms "map", "reduce", and "filter". What most people don't realize is that .NET 3.5 added all three of these algorithms, but it gave them very SQL-ish names, based on the fact that they're part of LINQ.

"map" => Select
Transforms data from one form into another

"reduce" => Aggregate
Aggregates values into a single result

"filter" => Where
Filters data based on a criteria

The ability to use LINQ to do inline work on collections that used to take iteration and conditionals can be incredibly valuable. It's worth learning how all the LINQ extension methods can help make your code much more compact and maintainable.


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!


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()}

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.


I think one of the most under-appreciated and lesser-known features of C# (.NET 3.5) are Expression Trees, especially when combined with Generics and Lambdas. This is an approach to API creation that newer libraries like NInject and Moq are using.

For example, let's say that I want to register a method with an API and that API needs to get the method name

Given this class:

public class MyClass
{
     public void SomeMethod() { /* Do Something */ }
}

Before, it was very common to see developers do this with strings and types (or something else largely string-based):

RegisterMethod(typeof(MyClass), "SomeMethod");

Well, that sucks because of the lack of strong-typing. What if I rename "SomeMethod"? Now, in 3.5 however, I can do this in a strongly-typed fashion:

RegisterMethod<MyClass>(cl => cl.SomeMethod());

In which the RegisterMethod class uses Expression<Action<T>> like this:

void RegisterMethod<T>(Expression<Action<T>> action) where T : class
{
    var expression = (action.Body as MethodCallExpression);

    if (expression != null)
    {
        // TODO: Register method
        Console.WriteLine(expression.Method.Name);
    }
}

This is one big reason that I'm in love with Lambdas and Expression Trees right now.


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"

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;

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


Everything else, plus

1) implicit generics (why only on methods and not on classes?)

void GenericMethod<T>( T input ) { ... }

//Infer type, so
GenericMethod<int>(23); //You don't need the <>.
GenericMethod(23);      //Is enough.

2) simple lambdas with one parameter:

x => x.ToString() //simplify so many calls

3) anonymous types and initialisers:

//Duck-typed: works with any .Add method.
var colours = new Dictionary<string, string> {
    { "red", "#ff0000" },
    { "green", "#00ff00" },
    { "blue", "#0000ff" }
};

int[] arrayOfInt = { 1, 2, 3, 4, 5 };

Another one:

4) Auto properties can have different scopes:

public int MyId { get; private set; }

Thanks @pzycoman for reminding me:

5) Namespace aliases (not that you're likely to need this particular distinction):

using web = System.Web.UI.WebControls;
using win = System.Windows.Forms;

web::Control aWebControl = new web::Control();
win::Control aFormControl = new win::Control();

  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

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.


Maybe not an advanced technique, but one I see all the time that drives me crazy:

if (x == 1)
{
   x = 2;
}
else
{
   x = 3;
}

can be condensed to:

x = (x==1) ? 2 : 3;

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;

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?


Using @ for variable names that are keywords.

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

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

Environment.FailFast()

Avoid checking for null event handlers

Adding an empty delegate to events at declaration, suppressing the need to always check the event for null before calling it is awesome. Example:

public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!

Let you do this

public void DoSomething()
{
    Click(this, "foo");
}

Instead of this

public void DoSomething()
{
    // Unnecessary!
    MyClickHandler click = Click;
    if (click != null) // Unnecessary! 
    {
        click(this, "foo");
    }
}

Please also see this related discussion and this blog post by Eric Lippert on this topic (and possible downsides).


"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)



lambdas and type inferrence 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