Recently I started jotting down anything new that made me say "oh cool!". Some are rarely used C# language features, some are API mechanics, and some are just random trivia. Here's what I've come up with so far:
C#'s stackalloc Keyword
stackalloc is basically handy way to allocate an array on the stack and can provide several conveniences.
Instead of allocating a locally scoped array (which is backed by the heap and managed by the garbage collector), you can get better "bare metal" performance by using stackalloc:
float SomeFunction(float[] input)
{
float dataResults;
float[] data = new float[3];
// we are calculating a result from input and storing interim results in data
return dataResults;
}
At the end of this method, a float array is sitting around waiting to be garbage collected. Instead, that function can become:
unsafe float SomeFunction(float[] input)
{
float dataResults;
float* data = stackalloc float[3];
// do something with the data and input
return dataResults;
}
In addition to taking the garbage collector and heap allocation out of the equation to eek out a little more performance, you also get a native float pointer. This can make interop with unmanaged code quite friendly, rather than a giant mess of fixed statements that would come about as a result of using float arrays.
C#'s ?? operator
Consider the following method:
Foo EnsureNotNull(Foo foo)
{
if (foo != null)
return foo;
return new Foo();
}
You can trim that down a bit by using a ternary operator:
Foo EnsureNotNull(Foo foo)
{
return foo == null ? new Foo() : foo;
}
But why use that when ?? is a binary null check operator; I.e., it returns the left if it is not null and the right otherwise:
Foo EnsureNotNull(Foo foo)
{
return foo ?? new Foo();
}
Hardware Graphics Acceleration and Asynchronous Calls
This is a tip I learned way back in my hay day of amateur game development. Many OpenGL/Direct3D may be just asynchronous calls on the hardware, and subsequent operations may end up resulting in them waiting for the previous operation to finish. The following is a very common pattern in drawing routines:
void OnPaint()
{
glClear(GL_COLOR_BUFFER_BIT);
// paint a bunch of stuff
// glDrawStuff();
glSwapBuffers();
}
Here, the code is immediately making paint operations following the clear. This results in those operations waiting until the clear has completed before executing. Restructuring the code as follows can squeeze out a little more performance:
void OnPaint()
{
// paint a bunch of stuff
// glDrawStuff();
glSwapBuffers();
// clear the buffer after the background and foreground are swapped
// this clear will take place asynchronously and be complete
// when we start to draw the next frame!
glClear(GL_COLOR_BUFFER_BIT);
}
I implemented this in GLMaps recently, and saw an FPS increase from 49 to 51. That's a ~4% increase! Using this technique, any static preprocessing/setup can actually just be run at the end of the drawing operations, rather than at the beginning. (Concurrently using the CPU and GPU between frames to get a net gain in FPS)
Handy C# 3.0 Shorthand
This tip didn't actually catch me by surprise, since I read through the C# 3.0 new features. However, old habits die hard, so I often forget to use them. Prior to C# 3.0, the following would be a standard class declaration:
class Foo
{
int myBar;
public int Bar
{
get
{
return myBar;
}
set
{
myBar = value;
}
}
double myMoo;
public double Moo
{
get
{
return myMoo;
}
private set
{
myMoo = value;
}
}
float myCool;
private float Cool
{
get
{
return myCool;
}
set
{
myCool = value;
}
}
}
With C# class declaration shorthand, developers can now eliminate much of the redundancy (the properties and backing fields are implicitly defined):
class Foo
{
public int Bar
{
get;
set;
}
public double Moo
{
get;
private set;
}
public float Cool
{
get;
set;
}
}
Also, when declaring an instance of that class, prior to C# 3.0, a common pattern is to set some initial properties:
void MakeFoo()
{
Foo foo = new Foo();
foo.Bar = 0;
foo.Cool = 0;
}
With C# 3.0, you get additional shorthand (less characters, not lines), and a more aesthetically pleasing syntax:
void MakeFoo()
{
Foo foo = new Foo()
{
Bar = 0,
Cool = 0
};
}
That's it for tips for now. Share 'em if you got 'em!