.NET 3.5: Properties and Delegates: A New Solution to an Old Problem

programming 3 Comments

A while ago I ranted about how .NET properties didn’t play nice with delegates. The gist was that, if you had a property and a method which took a delegate of the appropriate type, you had to write your own new delegate method, even though the property’s getter and setter would ordinarily qualify. Here’s an example:

public class Foo {
  public String Bar { get; set; }
}

public delegate String GetString();
public void display(GetString getString){
  Console.WriteLine(getString());
}

public void performOnAValue(Action <String> action){
  action("A Value");
}

Foo foo = new Foo { Bar = "bar" };
// You can't do this, because .NET doesn't recognize
// Foo.Bar.get() and Foo.Bar.set() as valid methods
// performOnAValue(foo.Bar);    // foo.Bar.set() satisfies Action<String>
// display(Foo.Bar);            // foo.Bar.get() satisfies GetString

// Instead you have to do this in .NET 2.0:
performOnAValue(delegate(String value) {
  foo.Bar = value;
});
display(delegate() {
  return foo.Bar;
});

Unfortunately, .NET 3.5 doesn’t fix this. However, it does give us enough new features that we can fake it. Consider this:

public static class Getter {
  public static T get<T>(this T target) {
    return target;
  }
}

This extension method adds a get() method to every type. That means that we can do this:

display(foo.Bar.get<String>);

Even though Getter.get() doesn’t satisfy the GetString() signature (since it takes a <T>), .NET is smart enough to figure out that if you call it as an extension it will work.

The bad news is that you do have to specify the type of the object as the generic type parameter of get(). You could write a non-generic version that gets and returns an Object, but that leads to the potential for InvalidCastExceptions. The good news is that if you do use the wrong generic type parameter (let’s say foo.Bar.get<int>), the compiler will complain (albeit with a confusing error message).

More bad news: there’s no equivalent extension method for the setter. Without resorting to reflection, there’s no way (that I am aware of) to programmatically access an arbitrary property of an object from within a method. However, lambda expressions make the pain of writing a delegate a little easier to bear:

performOnAValue(value => foo.Bar = value);

You can also do the same for the getter, if you use an empty input parameter list and an inferred return keyword:

display( () => foo.Bar );

I’m not sure whether the lambda or the extension method getter is less ugly.

With these options, I’d say that the Stupid .NET Trick of properties and delegates is about 75% solved. The syntax is not as clean as it could be, but it’s a big step forward… possibly enough to make properties worth it again.

.NET 3.5: Lambda Expressions, Type Inference, and Anonymous Methods

programming No Comments

As of v2.0, .NET already had support for first-class function types through delegates. v3.5 adds in a new concise syntax for creating short delegates.

public void performOnAllMembers(Action<Foo> action) {
  foreach( Foo foo in datastructure ) {
    action(foo);
  }
}

// Old syntax
performOnAllMembers(delegate(Foo foo) {
  foo.bar();
});

// New Lambda Syntax
performOnAllMembers( foo => foo.bar() );

Besides shortening “delegate” to “=>”, most of the keyboard savings here comes from type inference; you no longer have to declare that “foo” is a “Foo” since performOnAllMembers() already declares that it needs an Action to perform on a Foo. Note that this is just an assumption in the source code; everything is still strongly typed and the compiler will complain if you pass anything that’s not compatible with “Foo”.

Too Much Type Hiding?

While the source code does look cleaner, I generally believe explicitness is a virtue, and type inference works against that. If you don’t happen to have the method signature/documentation/source code for performOnAllMembers() handy, then you might be left wondering exactly of what type foo is and what it’s capable of. That means that you have to interrupt your flow of reading the source to go and look up the performOnAllMembers() contract; this interruption can only hurt your ability to understand what’s going on. The relaxed-typing proponents claim that this isn’t a big deal; I haven’t had a lot of experience with non-strong typing so I’m cautiously withholding judgment.

Anonymous Types

.NET 3.5 takes type inference one step further with anonymous types. These are similar to the Java anonymous inner types, except with a better syntax:

var myReference = new { Foo = "foo", Bar = 1 };

myReference points a instance with a strong type, and behaves as such; the type name is just hidden. Combined with the new property initialization syntax, .NET comes very close to having tuples. However, there’s a big catch with anonymous types: they’re only valid as local variables. That means you can’t pass them as parameters, get them as return values, or use them as generic type parameters (which means they can’t be stored in generic collections except as Objects). Moreover it doesn’t appear that they can ever be given methods; they’re basically local, dynamically generated structs (and I mean C dumb structs, not C# wannabe-classes structs).

There’s also something to do with lambda expressions called “Expression Trees”. I haven’t investigated this in detail yet, but it looks promising. Scott Guthrie has more to say on it. I’ll probably post more once I read up on it.

.NET 3.5: Extension Methods

programming 1 Comment

Extension methods are static methods that, through the magic of the compiler and Visual Studio’s IntelliSense, can be made to appear as if they’re actually members of a particular type. The key is that the target type can be any type, including the standard .NET types. Thus, if you want to add features to a 3rd-party class, you don’t have to resort to Booch utilities.

public static class MyExtension {
  public static String prefixWith(this String target, String prefix ){
    return prefix + target;
  }
}

String result = "foo".prefixWith("bar");

This is a decent feature, although I have two concerns:

  1. There’s potential for developer confusion, especially with developers reading unfamiliar code. “prefixWith()” isn’t a standard known method of String so you’re going to be thrown for a bit of a loop when you see it. Ordinary static methods at least have a big class name attached to them so it’s obvious when you’re using nonstandard code.
  2. I’m yet not sure how extension methods avoid name collision, but it’s bound to become an issue. All you have to do to attach an extension method on potentially every type in the system is to import the namespace of a class that defines the extension method. That can get out of hand quickly.

Lastly, there’s one cool feature with extension methods: since they’re just syntactic sugar for a static method, they don’t require an actual instance in order to “use them on a reference”. So I could have:

public static class MyExtension {
  public static bool isNull(Object o ){
    return o == null;
  }
}

String foo = null;
return foo.isNull();

By the way, that sound you hear is the Ruby enthusiasts snickering.

.NET 3.5: Property Enhancements

programming 2 Comments

.NET 3.5 adds a few syntax enhancements regarding properties.

Automatic Properties

You no longer have to declare the private field, getter, or setter methods when creating a property; the compiler will handle it for you.

class Foo {
  public String Bar { get; set; }
}

When I first started learning .NET, I actually thought that this feature had already been built into the language, and was surprised when I found I had to write my own (repetitive) property code. Automatic properties finally alleviates that.

Note: You can only declare read-write automatic properties. If you want a read-only or a write-only property, you have to do the legwork yourself. Note that access modifiers can still be used, so you could have a public property with a private setter — but that’s not the same thing as read-only.

Property Initialization

There’s a new syntax for assigning values to properties during object creation:

Foo foo = new Foo { Bar = "bar", Baz = 1 };

If you have mutable objects that don’t have any constructor logic, then this enhancement helps reduce a lot of verbose dereferencing code with a nice constructor-like syntax. Generally I prefer my classes immutable and constructor-populated, but there’s lots of times where that’s not feasible.

This makes two worthwhile enhancements to properties. Unfortunately, by themselves they wouldn’t do me much good: I intentionally avoid using properties (in favor of explicit getter/setter methods) because properties are completely unusable with delegates. However, some of the other new .NET features help to compensate for this, so I’m still counting these features as a win.

.NET 3.5

programming 1 Comment

The latest version of the .NET Framework, v3.5, was released yesterday. As usual, there’s a bunch of new libraries and Visual Studio enhancements (particularly when it comes to web applications). Those are nice, but what really caught my attention was the core language enhancements, which are pretty significant.

Scott Guthrie is one of the head honchos in that particular neighborhood of Microsoft. His blog talks about the new language features in pretty good detail, so I’m going to keep the descriptions to a minimum and focus more on commentary.

This post got pretty long so I decided to split it up:

Stupid .NET Tricks #9

programming No Comments

The HTMLSelect.Name is always the same as its ID/UniqueID properties. The documentation states:

Use the Name property to determine the unique identifier name for an HtmlSelect control. In this implementation, the get accessor returns the value of the Control.UniqueID property. However, the set accessor does not assign a value to this property.

The set accessor does not assign a value to this property because the Name property must have the same value as the Control.UniqueID property for the HtmlSelect control to work properly.

Thus, you can’t output an HTML <select> element that has different values for the “name” property and “id” attributes… unless you re-implement the code to do so yourself.

This isn’t the case for most other controls in the System.Web.UI.HtmlControls namespace. There’s no stated reason why the restriction is so necessary either. You have to really wonder WTF is going on over at Microsoft for a team to code in a seemingly arbitrary restriction and document it but not fix the problem in the first place.

Stupid .NET Tricks #8

programming 2 Comments

ASP.NET, in its grand paternal wisdom, replaces the “id” attribute on any server-side-enabled control with a dynamically generated (and thus guaranteed to be unique) value. So, when you write this:

<div id="foo"></div>

…what you actually get is something like this:

<div id="ctl00$page_content_replace$ctl00$foo"></div>

…thus dashing any hope you had of writing proper DOM-aware content (such as JavaScript and CSS).

Update: Oh yeah, and it changes the “name” attribute of input fields too, thus ensuring that your form parameters and query strings are utterly nasty.

Update 2: JonEHolland writes (below):

Use the ClientID attribute to specify ID once the control is rendered.

IE:

<div ClientId=”someId” id=”ServerSideId” runat=”server”></div>

Renders:

<div id=”someId” ></div>

I tried setting ClientId (and ClientID and clientid) and it didn’t help for several reasons:

  1. ASP.NET did not actually copy my server-side ClientID attribute to the client-side ID attribute as JonEHolland stated. The id attribute was the same generated string.
  2. It did, however, pass the same ClientID attribute and value on to the client (basically it left the unrecognized attribute alone, as it should). That could be somewhat useful, especially if you’re generating arbitrary XML. However, it doesn’t solve the core problem of the munged IDs; CSS/JavaScript won’t recognize ClientID without a lot of extra hacking.
  3. ClientID isn’t valid in the XHTML 1.0 Strict DTD, so Visual Studio complains about it. If you use any uppercase letters (such as ClientID) it actually generates an error; if you stick to lowercase (clientid) it lets you off with a warning.
  4. On the C# side: the ClientID property of Control is read-only and thus not changeable to anything. (ID is changeable but the change is ignored/overwritten by the time the control is rendered — at least as far as I’ve probed. Perhaps there’s a point in the control lifecycle where you can actually set it? Even if there is it appears to be too dicey to be worthwhile.)
  5. The ClientID property does provide me with the ID that ASP.NET has chosen for the element. If I wanted to generate CSS or JavaScript that used the element’s ID, I could use this property to discover the ID that would be used. But that’s horribly ugly and restrictive.

Sorry, JonEHolland; it doesn’t look like this works. If I’ve missed something let me know, but it appears that you’re incorrect.

Update 3: JonEHolland points to this blog post by Rick Strahl which describes how to bypass the ID munging by overriding the UniqueID and ClientID properties. That’s better than nothing, and just fine if you’re developing your own controls, but it still doesn’t solve the problem for the standard ASP.NET controls (in System.Web.UI.WebControls and System.Web.UI.HtmlControls); you’d have to create a whole bunch of new classes.

Refining Requirements

business, programming 4 Comments

My old boss, “Teflon” Ted, has written a great post on producing “digestible” requirements:

I commonly get “requirements” documents from clients that read like a college book report, just pages and paragraphs of disorganized stream-of-consciousness ramblings. When this happens, I use a little trick to restore some order to the chaos. I break it down into one long checklist of digestible tasks.

He then illustrates his process for taking a verbal description and refining it into a beautifully clear and concise list of tasks. It’s well worth a read.

Lately I’ve been getting back into the requirements ends of things after years of being implementation-only, so I’ve been especially interested in this sort of topic. I think I’ll adopt Ted’s checkbox method straight away (it’s certainly easy enough to do so), but I would like to expand on it a bit.

For starters, let’s take his example verbal/written requirement:

“We’re tired of users mistyping their passwords and not being able to access their new accounts. First of all, we want to add a password confirmation field to the sign-up form. Secondly, we want to force them to pick a password between eight and twelve characters. This should make their accounts a little more secure.”

Aside: I think he’s being extremely generous with the example requirement here. I’ve dealt directly with some of the requirement text that he’s been involved with too, and it’s usually a lot worse than this in terms of length (either overly wordy or overly sparse), clarity, and grammar/spelling.

Ted splits it into four sentences, and then drops the first and the last, neither of which are actually requirements. The two remaining sentences are then trimmed down and split up into action items and assigned check boxes.

That’s well and good, but I’d like to take a closer look at those two dropped sentences:

We’re tired of users mistyping their passwords and not being able to access their new accounts.

…and…

This should make their accounts a little more secure.

These are definitely not requirements, if you define “requirements” as “items to be acted upon.” However, they are, I think, important, and deserve to be included in a formalized / reorganized specification.

So, if I were to improve upon Ted’s method, I’d then restate the first and fourth sentence as:

  • Problem: Users are not able to access their accounts due to incorrectly answered passwords.
  • Goal: Make user accounts a little more secure.

From here, we can then ask several important questions:

  1. Is the problem clearly stated?
  2. Is the problem actually occurring?
  3. Are the stated (assumed) causes of the problem correct?
  4. Is the problem worth solving (or at least worth investigating further to determine the costs of solving)?
  5. Does the goal really address the problem?

If you get negative answers to any of these questions, then the requirements need to go back to the submitters for more discussion before the action items are refined further. If the problem and goals aren’t solid, then it won’t matter how well the requirements are organized and implemented; the whole thing will fall apart at the foundation anyway.

Once that’s done, you can then refine the requirements, and then ask:

  • Will the action items, if implemented correctly, achieve the goal (and thus solve the problem)?

Of course, all of this work should already be done in advance of anyone in the implementation department (ex: software developers/designers/architects) gets near it. That is to say, the people in the business/marketing/management department should have already asked and answered these questions. However, it’s been my experience that pretty much everyone with a non-technical background does not (and sadly, can not) perform this kind of investigation to an acceptable degree… and thus the people lower down the chain have to compensate.

Stupid .NET Tricks #7

programming No Comments

The people who dreamed up the .NET API (most particularly the graphics APIs) and their documentation often make my mind boggle.

For instance, what would you think if someone said to you: “You have 5 different options. Four of these are exactly the same. The other one is sometimes the same and sometimes not (though we can’t say when or why), and you’re not allowed to choose it some of the time.”

That’s exactly what the official documentation for System.Drawing.Pen.Alignment states:

This property determines how the Pen draws closed curves and polygons. The PenAlignment enumeration specifies five values; however, only two values—Center and Inset—will change the appearance of a drawn line. Center is the default value for this property and specifies that the width of the pen is centered on the outline of the curve or polygon. A value of Inset for this property specifies that the width of the pen is inside the outline of the curve or polygon. The other three values, Right, Left, and Outset, will result in a pen that is centered.

A Pen that has its alignment set to Inset will yield unreliable results, sometimes drawing in the inset position and sometimes in the centered position. Also, an inset pen cannot be used to draw compound lines and cannot draw dashed lines with Triangle dash caps.

I’m not sure which is worse: documentation that explains the stupidity of an API, or documentation that doesn’t explain the API at all:

System.Windows.FormsControl.IsMirrored Property
Gets a value indicating whether the control is mirrored.
Property Value: true if the control is mirrored; otherwise, false

(That’s all it says. There’s zero description of what “mirrored” actually means.)

These two examples are particularly bad, but the entire .NET API is filled with similar deficiencies in both documentation and design. Java’s standard libraries, while not perfect, are on the whole much, much better. If it weren’t too late already, the entire .NET team should be beaten over the head with a copy of Elliot Rusty Harold’s XOM Design Principles and then locked in a room until they cleaned up their mess. What they produced was simply amateurish.

Stupid .NET Trick #6

programming No Comments

As far as I can tell, you can’t handle key-repeating (ie: holding down a key for more than a brief period of time) in .NET without doing it manually through an obscene combination of KeyDown, KeyUp, and Timer. Google certainly doesn’t know how.

Update:After reading this blog I figured it out. There’s two gotchas involved:

  1. Multiple KeyDown (and presumably KeyUp and KeyPress) events are in fact fired when you hold the key down, even though this isn’t mentioned in the documentation.
  2. KeyDown isn’t fired at all for the arrow keys (even though KeyUp appears to be, at least in the code I had at one point) unless you convert the arrow key into an “Input Key”, via either PreviewKeyDown or IsInputKey. Since I was concerned with the arrow keys I happened to not realize the above point in testing.

Though it works, and in retrospect is quite easy to implement, it’s obscure enough that I’m not de-classifying this as a Stupid Trick.

« Previous Entries Next Entries »