Mr. Softwarepants

 
Python/Django/.NET/C#/Database project? Hire me.
22
May
2008

.NET library needed

Anyone know of a non-crap command-line parsing library for .NET? Preferably free, with BSD-style or better licensed C# code.

Update: When in doubt, fall back. In the past I've used a reflection-based command-line library. It originally showed up on GotDotNet, but GotDotNet is retired and the source hasn't migrated to anywhere else official. Googling for the class names, it does show up in a couple of open-source .NET projects.

Neither my old copy nor any of the borrowed copies seem to contain any licensing information. At least, there were none in any of the original file headers. I suppose I could contact the original author, but in the meantime I'll consider the code abandoned and up for grabs (in terms of licensing.)
4
Mar
2008
ReSharper Horizons: Varification -- Using Implicitly Typed Locals.
Defending ReSharper's preference for "implicitly typed locals", aka "vars".
26
Nov
2007

Stripping the PsExec banner in C#

Non-robust C# code to strip out only the remote output from a PsExec invocation:
Regex re =
  new Regex(@"www\.sysinternals\.com\s*(.*?)Connecting to " + targetMachine,
    RegexOptions.Multiline | RegexOptions.Singleline);
27
Aug
2007

Exception handling

C# provides the usual try/catch/finally style exception handling.

Because exception handling is built in to the language as keywords, it doesn't immediately lend itself to modularization. Just as you might remove explicit for loops in favor of a "map" idiom, I want to remove explicit catch blocks to allow more modular exception handling.

I have a base class that provides some services, including error handling for some common database-layer exceptions. Derived classes need to handle more specific errors that apply only to them.

Microsoft's Enterprise Library has an "Exception Handling Application Block" (EHAB) that tries to solve this problem. Presonally, I think the additional cognitive load of having XML configuration files is overkill in this case. (Also, referencing exception handling classes from XML instead of code means ReSharper doesn't know about the association.)

My in-code solution is for the base class to catch the exception types that it must handle, then in the catch(Exception ex) fall-back, I call a protected virtual function. This function can be overridden in derived classes. If it returns true, the exception is considered "handled" and no further processing happens. Otherwise, the default "I don't know what you just did" function kicks in.

As a thought experiment, I'm trying to figure out when the EHAB would "provide value." How complicated does your error handling have to get before defining mappings in verbose XML files becomes a net win?

Thought: Does it just come down to C# 2 not having literal hash syntax?
20
Apr
2007

Be careful with enums and default values

If you don't assign values to your enums in C#, the compiler will do it for you. It will start at 0 and increment for each name.

This code:

private enum LoadStatus
{
	LoadRequired,
	Loading,
	Loaded
}

private LoadStatus loadStatus;
is equivalent to this code:
private enum LoadStatus
{
	LoadRequired=0,
	Loading=1,
	Loaded=2
}

private LoadStatus loadStatus = LoadStatus.LoadRequired;

Note: enums, like integers (which they are underneath) default to 0 by the compiler as well.
So what? So if you aren't explicitly assigning values, and decide to add a "None = 0", then loadStatus will default to None instead of LoadRequired. Which in my case, caused almost all of the unit tests to fail immediately.

Moral of the story?
If you don't assign explicit values to your enums (for whatever reason), at least initialize your variables instead of relying on default behavior.

·
16
Feb
2007

SCOPE_IDENTITY in Sql Server & ADO.NET

With ADO.NET and SQL Server, SCOPE_IDENTITY() in SQL returns a Decimal value back out to C#. This is "to be expected", since decimal columns are allowed as identities, and in SQL the decimal type is a superset of all other possible identity column types.

At the C# layer, you can't cast a decimal to a long, so you'll either need to use Convert.ToInt64 in C# or select cast(scope_identity() as bigint) in the SQL.
·
12
Feb
2007

Generic classes and static members

In C#, let's say you have a generic class with a static member.

Even better, let's say its a generic static class. A static class, new in C# 2.0, is a class where the compiler will refuse to go if there's any non-static (or non-const) stuff in the class definition.

Static classes are the recommended way of adding "utility functions". Though I suppose that will change in C# 3.0, when extension methods come around.

Given this class:
static class MyClass<T> { public static int aValue; }

The static member aValue is not shared between concrete instances. MyClass<long> and MyClass<string> have different shared aValues.
This may or may not surprise you, depending on what you expect (ie, depending on how much you know about generic classes in general.)

Here's another class, which makes it a bit more clear what's going on:
static class MyOtherClass<T> { public static T aValue; }

In this case, there's no meaningful way for concrete type of this class to share aValue, since it has a different type in each case.
8
Feb
2007
The Code Project: Fast/Compact Serialization Framework.
21
Sep
2006

using IDisposable

Here's a stupid C# class which implements IDisposable (that is, can be used with using) and calls one function at the beginning and another at the end:

Source code for BeginEnd )

I won't vouch for its correctness; IDisposable is kind of tricky.

Example:
using(new BeginEnd(something.Init, something.Term)){ ... do stuff ... }

For extra cheesiness, derive stuff:
class WithSomething : BeginEnd {
	WithSomething(something) : base(something.Init, something.Term){}
}

using(new WithSomething(something)){ ... do stuff ... }

Sure, it's easy enough to do the same thing with try/finally, but this may increase understandability of a block in some cases.
1
Sep
2006

Saving form position.

In WinForms, Form has properties Height, Width, Top, and Left that let you read the current size and top left point of a window.
They also let you set the size and top left point in the future. Meaning, setting these properies doesn't "take" until the Windows event loop has a chance to do its thing.

This means if you set Form.Height and then immediately read it, it will still have the old value.

Surprising but accurate!

In any case, WinForms lets you get the current size and location of a form. And if the form is maximized, the size and location will reflect that.

Fun fact: the origin for a maximized form (on the primary monitor) isn't (0,0), it's a point just slightly negative in both directions. When you maximize a form the borders are sized off-screen, so the origin is negative by the border thickness.

The Win32 API has a function GetWindowPlacement that lets you get the "normal" size and location of a window. The normal placement is where the window would be if it wasn't maximized or minimized. This is also called the "restored" position.

In my 10 minutes of searching, WinForms doesn't give you access to the normal placement of a Form. Woot for pinvoke.net.

Now if you want to save the position of a form when it closes, and restore it on open, what you want to save is the maximized state and the normal position, not the current position. Setting the normal position before setting the maximized state will ensure that the form maximizes onto the correct monitor (instead of the first monitor), if neccesary.

The things I go through.
(For how long Trillian has been around, it has no excuse not to get multimonitor support correct, even in the of resolution changes and monitors coming and going.)
31
Aug
2006

What, did you learn OO in a barn?

In WinForms 2.0, ToolStrip has a property ToolStripItemCollection Items { get; }.
ToolStripDownDownButton has a property ToolStripItemCollection DropDownItems { get; }.

This means you can't write a class that can manage either items belonging to a ToolStrip or items belonging to a ToolStripDropDownButton without also writing a dicky adapter that lets you get at the children of the parent item (or type checking all over the place.)

Would it have killed Microsoft to name these properties the same thing, and stick them in an IToolStripChildren interface?

(Also, an IImageButton with Click, Image, Text properties would have been nice, so that regular buttons and toolstrip buttons could be treated somewhat the same. Without having to write... yet more adapters.)
Right about now I'm wishing C# (2.0) had multiple inheritence. Again.
So I could say "include the boilerplate NotifyPropertyChanged implementation" and "include the boilerplate INewContent implementation" and, etc.

Instead of having to copy and paste these chunks into every damn class that needs them.

You don't need it often, but when you need it you really need it.
22
Jun
2006
@ Head: DANGER ! String.IsNullOrEmpty can lead to runtime Null exceptions !!.

Crap!
18
Apr
2006

Factor out the middle

So one of the standard Code Refactorings is Extract Method.

You have some code like:
function Fa(){
  a1 // A bunch of code
  a2 // More code
  a3 // Yet more code
}

function Fb(){
  b1 // A bunch of code
  b2 // More code
  b3 // Yet more code
}

You decide that the code "A2" does some useful self-contained bit of work, so you rewrite to:
function X2(){
  a2 // More code
}

function Fa(){
  a1   // A bunch of code
  X2() // Now a method call
  a3   // Yet more code
}

function Fb(){
  b1 // A bunch of code
  b2 // More code
  b3 // Yet more code
}

It's quite possible that other functions will turn out to have "a2" stuck in them, so you change them to call the new function as well. "a2" and "b2" were equivalent:
function X2(){
  a2 // More code
}

function Fa(){
  a1   // A bunch of code
  X2() // Now a method call
  a3   // Yet more code
}

function Fb(){
  b1   // A bunch of code
  X2() // Now a method call
  b3   // Yet more code
}

Oh boy, duplicate code removed!

Going back to the original two functions, what if "a2" and "b2" are the blocks of code that differ, while "a1"="b1" and "a3"="b3"? Then I guess by the book you factor out the 1s and 3s to two new functions, and end up with a total of four:
function X1(){
  a1 // A bunch of code
}

function X3(){
  a3 // Yet more code
}

function Fa(){
  X1()
  a2 // More code
  X3()
}

function Fb(){
  X1()
  b2 // More code
  X3()
}

But if you have a lot of functions that share X1 and X3, bracketing the "useful work" starts looking weird after a while. At least, to me.

So in pseudo-C# 2.0, with anonymous delegates, I've would rewrite the above to factor out the middle:
delegate void AnOperation();

function TryX(AnOperation operation){
  a1 // A bunch of code
  operation(); // refactored middle
  a3 // Yet more code
}

function Fa(){
  TryX(delegate{
    a2 // More code
  });
}

function Fb(){
  TryX(delegate{
    b2 // More code
  });
}

Is that any cleaner? I don't know yet. It's 3 methods instead of 4. And the delegate signature doesn't have to be empty; it could take parameters that are set up in "a1" and cleaned up in "a3", to enforce some common error handling.

This occurred to me after reading about Python 2.5's with statement; it's certainly not as elegant looking.
7
Apr
2006

C# design question

I want to provide a pair of callbacks, one of which will be called when an action is performed.

This?
public interface IActionEnded
{
	void Completed();
	void Cancelled();
}
Or this?
public enum ActionResult
{
	None = 0,
	Completed = 1,
	Cancelled = 2
}
	
public interface IActionEnded
{
	void ActionEnded(ActionResult actionResult);
}

It almost doesn't matter, but I run into this choice occassionaly. Named methods on an interface, or fewer methods that take flags?

Maintainability is the key. If a "Failed" choice comes up in the future, is it better to force all implementors to implement a new method, or to accept a new flag that they weren't expecting?

A danger with the flag approach is writing code like: if (result == Cancelled) { do stuff } else { do other stuff}, and then having your "other stuff" run for all new future unexpected flags.

This is related to the "boolean turns into a set of flags" problem and the "true/false/null" problem, both from Database land.

More bad .NET documentation

Next we move on to the KeyPressEventArgs.KeyChar Property.

In Windows, there is a KeyDown event, a KeyPress event, an a KeyUp event. These are baked into the Win32 API and are Olde & Ancient.

The .NET versions of these events act the same way, and there's a list of which keys show up in KeyDown and which keys show up in KeyPress:

You can get or set the following keys:

  • a-z, A-Z.
  • CTRL.
  • Punctuation marks.
  • Number keys, both across the top of the keyboard and on the numeric keypad.
  • ENTER.

You cannot get or set the following keys:

  • The TAB key.
  • INSERT and DELETE.
  • HOME.
  • END.
  • PAGE UP and PAGE DOWN.
  • F1-F2.
  • ALT.
  • Arrow keys.

I'll note that they omit Backspace, which gets routed to KeyPress. Which means if you're doing character filtering in your KeyPress event always remember not to forget about backspace.

More bad C# samples

From the MSDN entry for Control.KeyPress comes this doozy of an example.

Code Sample )

First off, the article itself doesn't actually make any claims about what this code does... but a casual observer might think it allows only digits to be typed into a text field.

Not the case!

It only allows characters that appear on the number keys to be typed, which means you can type shifted numbers to get punctuation. Oops.

As a bonus, the bolded comparison is redundant and stupid.

28
Feb
2006
Cool Client Stuff: Saving out a Form's Size and Location using the Application Settings feature.

Visual Studio 2005's visual designer lets you bind component properties to application settings. Which seems like a good idea, until you realize what it means. It means that every time the component's property changes, lots of messages fly everywhere.

Which is, of course, what you wanted in the first place. But for Form size and location, it means your settings are getting updated and save constantly during a resize operation. Whoops.

So the post above gets an alternate way to save a Form's location. An alternate way which is also wrong.

It doesn't handle things like, say, multiple window instances. Or exotic things like if the screen resolution is different now than when you closed your Form, this code will happily resize it off screen.

Ok, it's just a "starting point", but I think the presentation is misleading. And you'd think that saving and restoring form state would be something Microsoft could just bake into the framework.

And on the subject of ApplicationSettingsBase: I'm beginning to think that "strongly typed application and user settings" are more trouble than they're worth. Or at least in the default implementation. I'd really like to be able to cram in my own settings at run-time, without having to define them in the project. Like, form states for every random form this application uses.

I suppose I could subclass ApplicationSettingsBase, but eww ick.

And versioning, too: And of course, your application settings are "versioned". Which means you need some extra code on app startup to upgrade your settings from one version to another, but it only works under certain circumstances.

Look, I just want a property bag for storing arbitrary window states. I've written that code before, but it wasn't meant to be used with multi-SDI apps. Looks like I'll have to dust it off and tune it up.
21
Feb
2006
C# 2.0 has lexical closures, in the form of "anonymous delegates." You can toss off an anonymous function definition in a lot of places. A lot like in JavaScript, actually, which is the language I've been using most often in my current non-work projects.

This link has been floating around: Create Elegant Code With Anonymous Methods, Iterators, And Partial Classes.

"Anonymous method" is actually "anonymous delegate", which is a closure. I guess calling them "closures" would scare too many people off. Heck. It's not like they're "continuations".
20
Feb
2006

enums in C# are braindead.

Look, we all know that enums in C# are stored as integers behind the scenes. You can even specify which integer type to use. (Though you should usually stick with int aka Int32.)

The fact that enums don't convert implicitly to or from integers isn't saving anyone from anything. Even worse, you can't switch on enum types. You have to cast them to an int in the switch, and then cast the values to ints in the cases.

This is heavily broken behavior.
Back
 
View my:
Reads
Links
Photos
Website
LinkedIn
Last.fm
GM scripts
Twits
Google Code
GitHub
Wiki

Back

The Piehead News
(C) 2003-2008
Adam Vandenberg