 Saturday, July 19, 2008
Don't call virtual methods in a constructor
I ran into a piece of code today similar to this: public class Base
{
public Base()
{
this.Initialize();
}
protected virtual void Initialize()
{
Debug.WriteLine("Base.Initialize()");
}
}
public class Derived : Base
{
public Derived() : base() {}
protected override void Initialize()
{
base.Initialize();
}
}
public class FurtherDerived : Derived
{
public FurtherDerived() : base() {}
protected override void Initialize()
{
Debug.WriteLine("FurtherDerived.Initialize()");
}
}
public class Tester
{
public static void Main(string[] args)
{
Base myBase = new Base();
Derived myDerived = new Derived();
FurtherDerived myFurtherDerived = new FurtherDerived();
Console.ReadLine();
}
}
See any problems here? Even though the compiler lets you call virtual methods from a base constructor, it's generally a "bad idea". That's because the constructor in the derived classes defers its construction up to its base classes before it executes its own constructor (even if we don't explicitly call the base constructor like in the example). Yet the call to a virtual function in the base class constructor is executed in the derived class implementation. This can cause subtle, unexpected problems.
In the example above, things "happen" to go well. It actually runs just fine. It outputs the following as you'd probably expect: Base.Initialize()
Base.Initialize()
FurtherDerived.Initialize()
But that's only because we didn't do anything significant in the derived constructors. What happens if we change the FurtherDerived class: public class FurtherDerived : Derived
{
StringBuilder _sb;
public FurtherDerived() : base()
{
_sb = new StringBuilder();
}
protected override void Initialize()
{
_sb.Append("FurtherDerived.Initialize()");
Debug.WriteLine(_sb.ToString());
}
}
Guess what happens when we run this code? FAIL!!! The dreaded, "Object reference not set to a reference of an object". Since the Initialize() method in the FurtherDerived class is called from the Base constructor, we are trying to access the _sb class level parameter before it's ever initialized. We are calling a method on an class we know has not been fully constructed. That ain't good.
The lesson is - never call a virtual method from a constructor. At best, you are introducing a bug waiting to happen. At worst, you've already done so.
Friday, July 18, 2008 11:57:17 PM (Eastern Standard Time, UTC-05:00) .Net | Back To Basics | C#
 Monday, July 14, 2008
Generating a random string in Groovy
A while ago, I wrote a post about using LINQ in C# to generate a random confirmation number. On my current gig we are using Groovy to write test scripts for SOAP UI acceptance test cases (incidentally, SOAP UI is a great web service testing tool that probably deserves its own blog post). In order to generate a dummy random string, I used an algorithm similar to the one I used in the LINQ post and wanted to show how it would be implemented in Groovy. // create the list of available characters
def availChars = []
('A'..'Z').each { availChars << it.toString() }
// even it out to about the same odds of getting a char or a number
3.times { (0..9).each { availChars << it.toString() } }
def generateRandomString = { length ->
def max = availChars.size
def rnd = new Random()
def sb = new StringBuilder()
length.times { sb.append(availChars[rnd.nextInt(max)]) }
sb.toString()
}
// print it out 10 times to see the randomness
10.times { println generateRandomString(8) }
If you're not familiar with Groovy, the -> symbol in the generateRandomString declaration marks a closure that takes one argument. In this case, it takes the desired length of the returned string. The last line invokes the closure n times. I really like (similar to Ruby) how you can pass function blocks as iterators over collections. It makes creating a loop both simple and intuitive (e.g. 10.times). And the syntantical sugar of creating a ranged list (e.g. 'A'..'Z') is another nice feature of the language.
Monday, July 14, 2008 2:21:50 PM (Eastern Standard Time, UTC-05:00) Groovy
 Tuesday, July 08, 2008
Windows Tips Using The Scroll Wheel
Like most developers, I'm a huge fan of the scroll wheel. It's a major part of my daily computing experience, so much so that I find I lose major productivity if I'm relegated to using just the scrollpad on my laptop. Now I've been using Windows for a while now. But I was amazed to learn something brand new today. Somebody posted a tip that you could simply "middle click" with the scroll wheel on a tab in Visual Studio to close out that document. So I fired up VS to test it out and sure enough, it works. That made me wonder ... is this a Visual Studio trick, or does it apply to any application with tabs? I fired up Firefox, IE, and Notepad++ and it works on all of them, too. I showed this little trick to a coworker who was also surprised to learn about it. He said, "I knew you could open new tabs by middle-clicking with the scroll wheel, but I didn't know you could close them, too." Huh??? "Sure. If you middle-click on a link in Firefox or IE, it will automatically open the link in a new tab." There you go - two tips for the price of none.
Tuesday, July 08, 2008 2:10:38 PM (Eastern Standard Time, UTC-05:00) Tips | Windows
 Monday, July 07, 2008
 Sunday, June 22, 2008
Enforce non-instantiability on static classes
Every project ends up with one or even possibly many static helper classes. If you program in Java, I'm willing to bet the house your project has a StringUtil class lurking around somewhere. These classes are easily abused, but can serve a valid purpose, such as a factory class responsible for creating instances. If these classes contain only static methods (as they usually do), there is never any reason for them to to be instantiated. However, in both Java and C#, it's easy to forget that if you do not explicitly declare a constructor, the compiler will generate a no-arg constructor by default. The consequence is that the following code is valid: StringUtil util = new StringUtil();
You've just allocated memory unnecessarily. Plus, the garbage collector will now incur extra overhead since it will have to reclaim this memory even though it was never actually used. All of the methods are static, so there is no reason to instantiate an individual object from this class.
To avoid instantiations, make sure you declare a private no-arg constructor. This will cause the compiler to throw an error any time the class is attempted to be instantiated. public class StringUtil
{
// constructor marked private since all methods are static
private StringUtil() {}
// bunch of static methods not shown
}
A side note - If you are using C# 3.0, I recommend using extension methods to enhance the behavior of existing classes rather than creating a something like a dedicated StringUtil class. First of all, any class declaring extension methods has to be marked as static and cannot be instantiated. And more importantly, it provides a much cleaner implementation to add those helper methods directly on the affected class. The added bonus is that Visual Studio is smart enough to provide Intellisense for extension methods on targeted classes.
Sunday, June 22, 2008 9:35:25 PM (Eastern Standard Time, UTC-05:00) Back To Basics | C# | Java | Programming
 Saturday, June 21, 2008
Macs to Java developers: You Want Me
At the next Java conference you're at, pay close attention to how many of the speakers are using Apple laptops. Here's a wild-ass guess - all of them. Well, maybe you'll find the one strange dude who didn't get the memo, but I'm not sure that guy is even allowed in the speakers' lounge. Now, I sort of get it. Apple makes beautiful machines. The hardware is top-notch, the UI is slick, it's UNIX based, and, probably most importantly to most Java developers, it's *not* Windows. Here's the odd part. In case you didn't know it already, OS X uses it's own JVM instead of using one provided by Sun. And Apple is notorious for lagging behind Sun with releasing updated versions of the JVM. They only recently released a 1.6 version of their JVM a month or so ago, but only with support for 64-bit Intel-based hardware (i.e. machines bought within the last 2 years). If Microsoft tried to pull off stuff like this, they would get absolutely killed in the press and blogosphere. None of this has seemed to slow down the spread of Java developers to the Mac. Is it clever advertising? The eye candy? A status symbol? The fact that it's not Windows? I think it's kind of like the whipped guy in college who was dating the super hot girl that always cheated on him. He knew it, she didn't exactly hide it, but he could never bring himself to break up with her because she was just too hot. His options were to either put up with her cheating, enjoy his turn at bat every now and then, and walk around campus with her on his arm; or go back to the minors and date somebody more in his own league. Steve Jobs famously said, "Java's not worth building in. Nobody uses Java anymore. It's this big heavyweight ball and chain." It is easily apparent to me that Apple doesn't view Java as a first class citizen on its platform. Are other Java developers blind to this fact? Do they hold out hope that things will change? Are they willing to put up with it for other reasons? As for me, I'm a happy Vista customer. :-P
Saturday, June 21, 2008 10:02:13 PM (Eastern Standard Time, UTC-05:00) Apple | Java
|