February 2005 - Posts

IL Editor

Want the most from your .NET applications? You want absolute control at the IL level? Then why not develop directly in IL... :)

A neat-looking IL Editor -- ILIDE#

Posted by PSteele | 2 comment(s)

Virtual PC Network Problems

I picked up an extra 512MB of RAM a couple of weeks ago to bring my development system up to 1GB of RAM. Now I've got a decent amount to play around with VS 2005 via Virtual PC. Last night, I created a VPC image with Windows Server 2003 but couldn't get it to talk to my network. I played around with this for close to an hour until I remembered that I have MAC Address filtering enabled on my DLink router. Only the MAC addresses I list can talk to the router. Once I added the MAC address from the VPC image to the list I was all set. Hopefully this will save someone else an hour! :)
Posted by PSteele | with no comments

Running in the IDE?

I was reviewing some old code samples I had laying around (cleaning off the hard drive so my backup set will fit onto a single 4GB DVD) and came across one about determing if you're running inside the VS.NET IDE. Well, VS.NET is a debugger, so you can use System.Diagnostics.Debugger.IsAttached.
Posted by PSteele | with no comments

Congrats to the Connecticut .NET Developers Group

Kudos to the Connecticut .NET Developers Group on their new DotNetNuke-based website. They contacted us about some DotNetNuke information and we were glad to help them get it going.
Posted by PSteele | 1 comment(s)

VB6, ByRef, ByVal and Interop

While COM Interop may have some drawbacks, many times it is a necessary step (budget constraints, time constraints, etc...). If you're currently developing VB6 objects that may some day be used in .NET via interop then now is the time to get your ByRef's and ByVal's cleared up. It will make your interop experience much more enjoyable.

As you probably know, passing an object "by reference" (ByRef) means the method that receives the argument can change the value of the argument. On the other hand, passing it "by value" (ByVal) means a copy of the argument is made and the method only receives a copy. There is no way to update the caller's argument that was passed in. VB6 has a default of "ByRef". However, unless you explicitly need to update one of your method arguments, you really should be passing everything ByVal.

Here's an example of where this can turn into a headache for you if you ever do COM Interop. He's a fictional VB6 "Clothes" object:

   Option Explicit

   Public Enum ShirtSize
      Small = 1
      Medium = 2
      Larger = 3
   End Enum

Public Sub BuyShirt(size As ShirtSize)
End Sub

You may have some VB6 code that consumes this method using:

   Dim myShirt As Shirt
    
   Set myShirt = New Shirt
   Call myShirt.BuyShirt(Medium)

And everything works just fine.

Now you create a wrapper for this COM object because you need to consume it from your brand new .NET application. Since VB6 defaults to ByRef arguments, the "size" argument in BuyShirt is a reference object. You may want to write some .NET code like this:

   Shirt myShirt = new ShirtClass();
   myShirt.BuyShirt(ShirtSize.Medium);

But that won't compile. You can't pass ShirtSize.Medium because .NET wants a ref parameter (just like the signature in COM). Therefore, to get this to work, you need an ugly workaround:

   Shirt myShirt = new ShirtClass();
   ShirtSize medium = ShirtSize.Medium;
   myShirt.BuyShirt(ref medium);

Consider yourself warned. Be wary of the VB6 code you're developing today and plan for the future.

Posted by PSteele | with no comments

Unit Testing is not difficult

Josh Holmes posts another article about his experiences with unit testing -- this time concentrating on the rather painless process of developing your unit tests with nUnit.

One thing I wanted to point out from his article. nUnit is based on jUnit. The inital port to nUnit had the same basic functionality as jUnit. Later, attributes were added to nUnit to make the process smoother and more "in tune" with what the .NET Framework has to offer. However, there's still some legacy code in nUnit that behaves like jUnit. Since Java doesn't have attributes, test cases were required to be public void methods that started with "Test". Even today, nUnit still exhibits this behavior and will treat any public void method with zero arguments that starts with "Test" as a test case. So while Josh's example showed a method called "TestGetIntegerFromConfigFile" decorated with the "Test" attribute, the code will run the same way from the nUnit GUI even without the attribute.

Here's a quick example showing this behavior:

using System;
using NUnit.Framework;
namespace NUnitCheck { public class Foo { public string Method1() { return "hello"; } } [TestFixture()] public class MyTest { public void TestMethod1() { Foo f = new Foo();
Assert.AreEqual("hello", f.Method1()); } } }

Interestingly, one of my favorite add-ins, TestDriven.NET, does not support this and uses attributes exclusively to find the test cases.

Posted by PSteele | 2 comment(s)

Static Cling? No, Static Wierdness.

I thought this was a little odd. As you may or may not know, static (Shared in VB.NET) members are not inherited. Since static members are members of the class, not an instance of the class, this makes sense. When you create a subclass, you're creating a new class so you don't get the static methods.

However, the compiler still lets you access the static methods of your base class. Example:

using System;

namespace InheritStaticsExample
{
	public class Foo
	{
		public static void Pack() 
		{
		}
	}

	public class Bar : Foo
	{
	}


	public class Test
	{
		public Test()
		{
			Bar.Pack();
		}
	}
}

This code compiles just fine. If you pull out ILDASM (or your disassembler of choice), you'll see that the call to Bar.Pack() is compiled into a call to Foo.Pack(). Kind of wierd. If I can't inherit static members, why can I call them from my subclass?

Now lets makes things a little more interesting. Suppose we add a static Pack() method to Bar. Then what happens?

using System;

namespace InheritStaticsExample
{
	public class Foo
	{
		public static void Pack() 
		{
		}
	}

	public class Bar : Foo
	{
		public static void Pack()
		{
		}
	}


	public class Test
	{
		public Test()
		{
			Bar.Pack();
		}
	}
}

This gives me a compiler warning (only a warning!):

The keyword new is required on 'InheritStaticsExample.Bar.Pack()' because it hides inherited member 'InheritStaticsExample.Foo.Pack()'

But Pack() is not an inherited member. And I would think a message saying "new is required" would be an error. I mean, it says its required, but I omitted it. The code compiles just fine into a call to Bar.Pack().

And K. Scott Allen has a great article on Statics at MSDN.

Posted by PSteele | with no comments
More Posts