Oct 22, 2009

Random Nerd Debates : Episode 2 VAR

In the second episode of Random Nerd debates we are doing to discuss the use of the C# keyword var.

First, what is var? MSDN has a very succinct explanation of the keyword:

“Beginning in Visual C# 3.0, variables that are declared at method scope can have an implicit type var. An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type.”

And the simple code example:

var i = 10; // implicitly typed
int i = 10; //explicitly typed


Ok so now that we are both on the same page let’s talk about usage of this keyword. I have a very specific rule when it comes to the usage of var.



I will only use the var keyword to shorten my code without obscuring the clarity. This means I will only use the var keyword if the type can be inferred directly by viewing the right side of the operation. By “directly” I mean that the type is explicitly specified in the right side of the operation. I don’t want to have to jump to the method declaration or hover over the expression to determine the type. The best way to show this is through code examples:



//Since foo is clearly specified on the right side I WILL use var in this case
var foo = new Foo();

//Since the return type of the method GetBar() is not clear I WILL NOT use var in this case
var bar = GetBar();

//Other places where I WILL use var
var foo = (Foo)bar;
var bar = foo as Bar;


The benefit of the var keyword is allowing to write more succinct code. To me, succinctness can not come at the cost of clarity. In my examples above where I WILL use var I don’t feel like I am sacrificing any clarity but I am reducing noise.



There are two exceptions to my rule. When writing a LINQ query you almost always see the use of var and so I will follow that convention



var files = from file in enumerableFiles
select new Uri(file.FullName,UriKind.Absolute);


The other exception is similar to the LINQ example but more specific. There are cases which I want to deliberately de-emphasize the underlying storage mechanism and keep it ambiguous. In these cases I will use var to purposely obscure the underlying type. Eric Lippert explained this idea well in a blog post. The tidbit from Lippert was this:



   “Another subtle point here: notice how when I changed the type of the variable "racks" from "array of string" to "set of string", I didn't have to redundantly change the type thanks to implicit typing of local variables. I want to emphasize the semantics here, not the storage mechanism. If I felt that communicating the storage mechanism was an important part of this code -- because it has such a strong effect on performance -- perhaps I would choose to emphasize the storage by eschewing the "var"."



If you don’t already follow Eric’s blog I highly recommend it.



So I pose the question to you? Do you use var? Do you have a specific rule you follow when it comes to using it? Did you read this whole post and realize you just wasted the last 20 minutes of your life?

Labels: ,

Oct 16, 2009

Seeing Stars I’m Seeing Stars

“Oh my, starry eyed surprise. Sun down to sun rise. Dance all night. We gonna dance all night…”

Feel free to stab your eyes out at this point (Or drink a Diet Coke)

Ok so WTF am I talking about? Custom Ink Canvas rendering in WPF of course… I ran across a problem recently that I thought was blog worthy. The objective was to allow a user to draw on an InkCanvas with a custom “stencil.” The “stencil” is really just some custom shape that should be used as the stroke for the InkCanvas. This is kind of hard to explain so a picture may help

SurfaceCustomInking[1]

In this picture the stars (hence the terrible Oakenfold reference) would be the stencil. When the user drags the mouse around the canvas we want to draw the stars like shown above. This isn’t quite as obvious to implement as most things in WPF. My hope was that I could just set the Stroke to some DrawingBrush and be done. However, it isn’t that easy.

The main reason for the complication is the way that the InkCanvas collects the strokes from the user. The strokes are are collected on a background thread to ensure that all strokes will be collected, even if the UI is blocking. This is done through a DynamicRenderer object. This object collects the user input and renders all points in the stroke on a separate thread.  Once the entire stroke is collected The InkCanvas raises the OnStrokeCollected method.

The first step to solving my problem is to implement a custom DynamicRenderer  that will track the users movements on the canvas and render our custom shape along the path that the user has drawn.

public class CustomRenderer : DynamicRenderer
{
private Point prevPoint;

public DrawingGroup Stencil { get; set; }

protected override void OnStylusDown(RawStylusInput rawStylusInput)
{
// Allocate memory to store the previous point to draw from.
prevPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);
base.OnStylusDown(rawStylusInput);
}

protected override void OnDraw(DrawingContext drawingContext,StylusPointCollection stylusPoints,Geometry geometry, Brush fillBrush)
{
for (int i = 0; i < stylusPoints.Count; i++)
{

var pt = (Point)stylusPoints[i];
Vector v = Point.Subtract(prevPoint, pt);

// Only draw if we are at least 4 units away
// from the end of the last ellipse. Otherwise,
// we're just redrawing and wasting cycles.
if (v.Length > 4)
{
var clone = Stencil.Clone();
clone.Transform = new TranslateTransform(pt.X, pt.Y);
drawingContext.DrawDrawing(clone);
prevPoint = pt;
}
}
}

}


The key to this snippet is in the OnDraw method override. I am iterating through the points along the path that the user has drawn then rendering a new instance of our custom drawing to the DrawingContext pipeline. Notice the TranslateTransform, I am using the translate to make sure the drawing I add to the DrawingContext pipeline follows the points in the path that the user created.



Once the stylus points are converted to strokes then the stroke is told to render itself. This is the second step in the process. We need to create a custom stroke class that renders our custom shape when it is asked to render itself.



class CustomStroke : Stroke
{
public DrawingGroup Stencil { get; set; }

public CustomStroke(StylusPointCollection stylusPoints) : base(stylusPoints)
{
}

protected override void DrawCore(DrawingContext drawingContext,DrawingAttributes drawingAttributes)
{
// Allocate memory to store the previous point to draw from.
var prevPoint = new Point(double.NegativeInfinity,
double.NegativeInfinity);

// Draw linear gradient ellipses between
// all the StylusPoints in the Stroke.
for (int i = 0; i < StylusPoints.Count; i++)
{
var pt = (Point)StylusPoints[i];
Vector v = Point.Subtract(prevPoint, pt);

// Only draw if we are at least 4 units away
// from the end of the last ellipse. Otherwise,
// we're just redrawing and wasting cycles.
if (v.Length > 4)
{
var clone = Stencil.Clone();
clone.Transform = new TranslateTransform(pt.X, pt.Y);
drawingContext.DrawDrawing(clone);
prevPoint = pt;
}
}
}
}


You can see the DrawCore method looks very similar to the OnDraw method in the custom renderer. We are doing the same rendering in both places so the code will be very similar.



The final step in this process is to create a class that inherits from InkCanvas and wire up the dynamic renderer and the custom stroke.



public class CustomRenderingInkCanvas : InkCanvas
{
readonly CustomRenderer customRenderer = new CustomRenderer();

public CustomRenderingInkCanvas(): base()
{
// Use the custom dynamic renderer on the
// custom InkCanvas.
DynamicRenderer = customRenderer;
}

protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e)
{
// Remove the original stroke and add a custom stroke.
Strokes.Remove(e.Stroke);
var customStroke = new CustomStroke(e.Stroke.StylusPoints)
{
Stencil = Stencil
};

Strokes.Add(customStroke);

// Pass the custom stroke to base class' OnStrokeCollected method.
var args = new InkCanvasStrokeCollectedEventArgs(customStroke);
base.OnStrokeCollected(args);
}
}


I have cut out some code from the snippet above to focus on the important parts. The two keys are wiring up the DynamicRenderer in the public constructor and removing the default stroke and adding in our custom stroke in the StrokeCollected override



Once we put all these steps together we end up with an ink canvas that we can apply a custom stencil to and use that stencil to draw with.



The result is shown in the video below ( Turn on your sound ;)




Custom InkCanvas in WPF from Brad Cunningham on Vimeo.


Note: the lag you see in the video is just from me trying to draw using the trackpad on my laptop with one hand. The actual application doesn’t lag.

You can download the full sample project from here. I followed this MSDN article in solving this problem

Labels: ,