Mr. Softwarepants

 
Python/Django/.NET/C#/Database project? Hire me.
30
Jul
2007

Too many tiers!

ADO.NET 2 has support for asynchronous command execution. Which is great, I'm sure, but since our application has "layers" I don't know how to take advantage of this.

All database accesses in the client go through the "service layer", which is access via .NET remoting. In the client code, you don't even know you're making remote calls. You just get a reference to an interface and make calls.

And then on the server side, all the real ADO.NET calls are hidden deep within the Entlib DAAB.

So even if I rewrote the search code to use asynchronous calls (ie, make searches cancelable), that's still all on the server-side. On the client side I'd also need to make use of asynchronous remoting calls, and then figure out how the heck to make a cancel on the remoting call turn into a cancel on the server side.

The problem is some combination of big and uninteresting, unfortunately.
11
Dec
2005

WinForms 2.0: INotifyPropertyChanged

MSDN: How to: Implement the INotifyPropertyChanged Interface

WinForms 2.0 has gained a lot of new interfaces and events for doing databinding.

By default, when an object property is bound to a WinForms control, the binding is "one-way". Changes to the control's value will be pushed to the object property, but changing the object property programmatically will not change the control's value (meaning, the value won't change in the UI.)

In WinForms 1.x, to implement two-way databinding a naming pattern is used (one of the few times in the .NET framework where naming is significant.) For a property "Color", an event "ColorChanged" needs to be exposed and fired when the value of "Color" changes. This leads to a lot of potential exposed events in some circumstances.

Per the MSDN link above, WinForms 2.0 lets you do all your property change notification through a single event, which takes the string name of the property as payload.

(Though also per the MSDN link above, the property getter implementation is total boilerplate. Add more boilerplate if you're tracking a dirty bit on your object, etc.)

C# Express: The Hell?

Visual Studio C# Express seems to be missing the docs for the System.ComponentModel namespace. LAME.

WinForms 2.0: "Generate Member"

WinForms 2.0: How to: Use the Modifiers and GenerateMember Properties

I stumbled upon this feature in Visual Studio 2005, and I hadn't seen it mentioned on Der Web. All controls on a WinForms form now have a "GenerateMember" property. If set to false, your Form class won't have a member for that control, but the control will still be visible at run time.

In previous versions of WinForms, every control (or component) added to a form added a member variable to the form. This sucked for forms with large numbers of controls that didn't need to be manipulated programmatically (for example, most Labels.)

This new (pseudo-)property lets you clear out some of the clutter in your GUI builder generated classes.

(The GUI builder implements this by making controls with no member local to the InitializeComponent method that all WinForms components have.)
28
Nov
2005

API design

IanG on Tap: C# 3.0 - Extension Methods

One of the new C# 3.0 language features is 'extension methods'. The basic idea is that the set of methods available on an instance of a particular type is open to extension. In effect, we can add new methods to existing types.

This is similar to Categories in Objective-C (and related concepts in Smalltalk), and the ability to add methods to prototypes in Javascript, and various other mechanisms in various other languages.

But the problem in comparing features across langauges is that similar things are always different, due to differences in the exact semantics of the rest of the language. Quick! What's an object? Answer: whatever heck your particular language spec says it is.

But I didn't write this to talk about any of the above; I want to comment on this:

Developers new to .NET tend to be surprised that calling ToUpper on a string doesn't convert it to upper case. And I think it's perfectly reasonably to be surprised. ToUpper looks like an imperative operation. Its form actively conceals the fact that it's really a function in the strict functional programming sense - it's has no side effects, it merely takes an input expression returns a result based on that input expression without modifying the input in any way. The input expression is the implicit this reference - the object on which ToUpper is invoked.

I think this form would have been more honest, and less likely to mislead:

String.ToUpper(input)

It's true that this would be more cumbersome, and would require more typing than what we've got today. But misleading code seems like a high price to pay for a little less typing - aren't we always being told that code will be read far more often than it is written? And even if you are convinced by the argument that a core class like String is sufficiently widely used that (a) it's worth the savings in this case because it affects everyone, and (b) everyone knows String so it doesn't matter that it's a special case, it still seems like the wrong thing to do in the general case.

Holy heck GOSH what a bad idea. Cumbersomeness matters, even with IDEs and autocomplete and IntelliSense and what have you.

What language are these programmers coming from that this construct is confusing? I suspect the answer lies here: UCase Function (Visual Basic).

I suppose it helps to have used langauges before where (1) strings are immutable and (2) method call notation is the norm rather than the exception.

21
Nov
2005

.NET: EventArgs

Krzysztof Cwalina: Why Do We Have EventArgs Class?

I've wondered this myself, as System.EventArgs is empty.

For example, we wanted to be able to add additional data to existing events without having to add more parameters to their corresponding event handlers, which would be breaking to existing clients. For example, we could add a Timestamp property to EventArgs, if we ever decided that we needed it. In other words, the EventArgs as a fixed root of the hierarchy gives us more control over what data is carried with events.

Except, of course, that anything added to the base class of such an exceedingly broad class tree would risk clashing with names defined in a concrete eventargs somewhere, thus breaking existing clients.

Note: On my previous WinForms project, I mostly ignored EventArgs, and didn't bother deriving my custom events from it.
15
Nov
2005

NUnit 2.2.3

NUnit 2.2.3 is out. It's what we use for unit testing at work.

I'ma gonna try it out tomorrow and see what's up.

NUnit-Gui 2.2.0 sucks, both because it tends to start throwing exceptions for no apparent reason if you use it for too long, and because the UI looks like it was designed by programmers. Not much that can be done about the latter, but maybe they've cleared up the former.

Update: "Service Unavailable"

Update: Back online. The download link is over on SourceForge. They haven't updated the download pages on their own site yet.

Notes on 2.2.3:

* Hooray, they're not using a custom font on the test tree anymore. (Boo for not coalescing tree paths that only have one branch, though.)
14
Nov
2005

C#: Join an array of strings

The built-in method String.Join() let's you join an array of strings with a delimiter. Except that it only lets you join an array of strings. string[]. This is an example of inhumane API design, as it requires gross incantations to get an ArrayList of strings joined.

Here's my method to join together an ICollection of any type of object, which are rendered to strings via ToString().

public static string Concat(ICollection items, string delimiter)
{
  bool first = true;

  StringBuilder sb = new StringBuilder();
  foreach(object item in items)
  {
    if (item == null)
      continue;

    if (!first)
    {
      sb.Append(delimiter);
    }
    else
    {
      first = false;
    }
    sb.Append(item);
  }
  return sb.ToString();
}

Stick this static method wherever you keep your other string utility functions.

11
Nov
2005

Explicit Interfaces in C#

C# lets a class implement an interface in two ways: the normal way, and "explicitly".

Explicit interfaces exist in the language so that a class can implement two separate interfaces even if both interfaces have a method with the same name.

Because of the "same name" issue, you can't call explicitly implemented methods directly on the class; you have to cast the class to the interface first. The manifests in the IDE in IntelliSense as explicitly implemented methods not showing up in the auto-complete list.

The C# langauge has array classes, like "string[]" and "MyClass[]". Behind the scenes these inherit from the .NET array class "Array". Array implements IList, but does so explicitly.

I hadn't made the mental connection until now, so I had been testing membership in an array such as:
string[] things = new string[]{"abc", "def", "ghi", "jkl"};

with code like:
bool found = -1 < Array.IndexOf(things, "abc");

Turns out this works too:
bool found = ((IList)things).Contains("abc");

Too bad it's also ugly, but at least that "-1" isn't hanging around.
9
Nov
2005

.NET Format Strings

Why the heckerford hell doesn't the C# compiler (or the Visual Studio 2003 IDE) throw compile-time errors on malformed format strings?

I just hit a runtime error because I used a square bracket instead of a curly bracket, and there was absolutely no reason for Visual Studio to even let the code compile. But hey, at least I passed in a string! Go static typing!
16
Oct
2005

C# Generic Collections

This article explains that while in C#, string[] is a subclass of object[], List<string> is not a subclass of List<object>.

This makes sense, and in fact, thinking about it (and messing around in VS2005 Express) enlightened me as to some problems in our current non-generic strongly typed collection classes.

(All of our strongly typed lists have methods to add "derived type" and "base type", because of inheritance. But that means the compiler won't complain if you add any derived type to a strongly-typed list, since it can be silenly converted through the base type. Now, if our goal is "compile time type checking" we're sunk; if it's just the convenience of not having to cast in and out of a base type list, then we're OK.)

As an aside, the names of the generic collection interfaces are the same (minus the <T>) as the names of the non-generic collection interfaces, and yet some of them are defined very differently. And I don't even know why Collection<T> is stuck under "System.Collections.ObjectModel" instead of "System.Collections.Generic".
8
Oct
2005

More of a guideline than a rule, really

I was going to post about how I wrote the must terrible C# event routing code ever at work Thursday afternoon.

I defined an interface INewContent, which has a single member "event NewContentHandler NewContent".

By implementing this interface, a class signals that it will be providing new content that it wants some control up the chain to process. There are only two ways to process content: display it or pass it on up the chain.

Now, the .NET class library guidelines say to (and the .NET framework does) implement a protected virtual method "OnMyEvenet(MyEventArgs e)" for every public event with signature "MyEventHandler(object sender, MyEventArgs e)".

The deal is, subclasses can override this method to do special case event raising. This is sometimes better than a class listening to its own events, as you can gaurantee the order in which your handling happens in relation to any other objects that have hooked the event.

Now, all the classes I have that implement INewContent had an OnNewContent, usually defined in a common base class. In most cases, I want an object that is listening to other objects' NewContent events to reraise the event as their own NewContent event.

The problem is, the event signature has an "object sender" parameter, but the event raising method doesn't (almost always, the event raising method sets itself as the sender.)

So I came up with some rigamarole in a static utility class to translate between the two kinds of methods.

Then the next morning I realized that I had been a slave to orthodoxy.

I took out OnNewContent(MyEventArgs e) from the base class and replaced it with HandleNewContent(object sender, MyEventArgs e).

Now when an object A listens to content from object B, it hooks the object B's NewContent event to its own HandleNewContent, which by default just reraises the event for whoever is listening to object A.

Still wonky, but much less so than having a separate static class that does event routing.

The moral of the story is, know when to ignore the guidelines.
6
Oct
2005

Using Back/Forward mouse buttons in .NET

The Code Project: Using Hooks from C#.

Sample code that shows how to process the Back and Forward mouse buttons in a .NET application, using the "Local Windows Hook." Also includes an IComponent that wraps up the hook and translates Windows Messages into useful .NET events.

It's all rather more complicated than it seems it ought to be, considering how long five button mice have been around now.
19
Sep
2005

HowTo: Mark an event as "NonSerialized" in C#

This may be common knowledge, but took far too long to figure out (as nothing helpful came up on a Google search.)

When using object serialization in .NET, the default serialization behavior is to serialize event handlers (and the objects which are listening) which leads to a couple of problems.

1) You're serializing out a larger object graph than you potentially need, since (in our case) we don't want events on the other side of the wire, just the object data.

2) Chances are the objects handling events aren't serializable, or have members which aren't serializable.

You can't mark a public Event as [NonSerialized] because there's some compiler magic going on behind the scenes, but you can mark a private Event, and provide a public event with add/remove accessors:

[NonSerialized]
private EventHandler myEvent;
public event EventHandler MyEvent
{
	add { myEvent+= value; }
	remove { myEvent-= value; }
}
Gross and non-obvious; the compiler should be smart enough to do this for you, but I guess I'll just have to see what C# 2.0 lets you do.
15
Sep
2005

Need some Unit Testing advice (NUnit)...

...and damned if I know if any of my actual readers can help.

I have a .NET assembly that defines a bunch of classes derived from T.
In my test I want to find all children of T, and test that they implement two methods (and don't return null.)

This is all working, via a single [Test] that uses Reflection to find the classes. I print the name of each type to the Console as I test them.

Is this good form?

On the plus side: Any new derived classes automatically get these tests. Don't have to right boilerplate per-class.
On the negative side: Possibly harder to track down problems if there are any.

The alternative is two create N*2 specific tests with specific names.

(Good thing we're starting some technical review meetings. Looks like I have another question for next week's agenda.)
9
Sep
2005

Yes, yes, having the source is good.

Debugging WinForms that use validation or databinding is hard.

The framework handles validation events and databinding behind or back, as it were, and when something goes wrong inside the methods you genreally end up with an exception in "non-user code" with the cursor pointing to your Application.Run() method in your main function.

Not the most helpful place to be when debugging. If .NET shipped with the full source to itself, at least you could see a useful stack-trace that was inside some internal DoValidation() method or somesuch.

I suppose it's possible to set up debug symbols, so I should check if that is a remote possibility at all. After all, we have these MSDN Hella Platinum subscriptions. Might as well use them.

(A long time ago, I was getting paid to use the TurboVision framework, which at the time shipped with Borland's C++ compiler with full source. It was also unsupported by that time. I actually did find a bug deep inside the valdation code, where they were setting a field to null instead of going through the ClearSomething method.)
7
Sep
2005
Just a quick note: If you're doing .NET programming, and using object serialization AND data binding (which implies having events hooked up), welcome to a world of hurt.

Event handlers aren't serializable, and can't be marked non-serializable, and will cause exceptions when you try to serialize an object with listeners before disconnecting. And it's annoying to disconnect events in the general case.
6
Sep
2005

And C# doesn't have mix-ins because...?

Oh, right, multiple inheritance is EVIL or some-such.

I'd really like to be able to define a mix-in that gives the target class these methods:
protected override void StartAdd()
{
	this.DefaultAddBehavior();
}

protected override void CancelChanges()
{
	this.DefaultCancelBehavior();
}

protected override void SaveChanges() 
{ 
	this.DefaultSaveBehavior();
}
I suppose I could cram them into a new layer of heirarchy, but that's just gross.

Another wishful use for a mix-in: A "CancellableEvent" mixin to add to an event class to get the bool Cancel property. Otherwise I have MyEventArgs : EventArgs and CancelMyEventArgs : CancelEventArgs which have to redefine their properties, instead of just being able to slot in a single bool.
2
Sep
2005

Clemens Vasters: Visual Studio Overload And The Specialization Gamble

And the development teams will change shape. Come Avalon, and game developers (yes, game developers) will be in great demand in places that are as far away from gaming as you could imagine. I’ve just had meetings with a very conservative and large investment management company and they are thinking hard about adding multi-layer, alpha-blended, 3D data visualizations complete with animations and all that jazz to their trading system UIs, and they’ve got the business demand for it. Of course, the visualization experts won’t be data mining and data analysis or software integration specialists; that’s left for others to do.

Dear large investment management company: letting game programmers anywhere near your codebase is an absolutely terrible idea.

1
Sep
2005
.NET Tool: Clean Sources

Visual Studio .NET 2003 is missing something that Visual Studio 6 had: an option to "clean" the current solution. This Explorer add-in lets you right-click on any folder in Windows to resursively delete all bin/ and obj/ subfolders.

Be careful! Don't go clicking it all willy-nilly where an installed app might have a bin/ folder.
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