First time here? Check out the site's "greatest hits" or read a post from the archives. Feel free to leave a comment or ask a question, and consider subscribing to the latest posts via RSS or e-mail. Thanks for visiting!
Page 1 of 14 in the Learning .NET category Next Page

Here's the results, as promised, of the .NET Survey I took last week.

Also, here's the disclaimer. I did this on a whim, it's not scientific, so the margin of error is +/-101%. That said, the results feel intuitively right to me, personally.

It was a single question with 14 checkboxes. You were asked to "check al the .NET Framework features that you use in your projects." The results are here after 4899 responses:

image

There were lots of good responses on Twitter and comments on the original blog post.

Folks wanted choices like "Other," "None" and "I don't use .NET." Of course, not answering the survey is a good way of reporting that. ;) In fact, 29 people looked at the survey, checked nothing and then just clicked Finish.

Here's some choice feedback:

  • A raw survey like this will be biased towards "new and cool stuff".
  • Sure you ain't shopping for an answer?...I use datareaders a lot. And datarepeaters. Everything else goes clunk.
  • Where's Silverlight?
  • No Linq-to-Objects?

I organized the survey in terms of what I called "subsystems." You could also say "product teams," I suppose. It was more trying to get a sense of the tools people reach for when they start a project.

I probably could have included IIS6, II7, etc., but I'm sure it would have gotten unruly. I could have included languages as well, but that feels like another survey. The one thing I regret not including was Silverlight. I wanted to add it, but by the time I'd realized it, I had already got 1000+ results and I decided adding it at that point would skew the results.

Of course, this could have been a multi-question, multi-page survey, but they you probably wouldn't have filled it out, right? I wanted to find a balance between getting a LARGE enough number of responses and getting data that's useful in some way to both you, Dear Reader, as well as the bosses I'll show it to.

As with all online surveys, this one is worth exact the paper its printed on. :) If you think it is useful, cool, if not, it only wasted 5 seconds of your time when you filled it out. Thanks for filling it out.

What is your analysis of the results?



imageBefore I graduated from College/University I was convinced that school was for lamers. Then I graduated from school and decided that NOT going to school was for lamers. That shows you what a wishy-washy person *I* am. ;) School is for some folks and not for others. Wear the shoe that fits you best.

Totally random retrospective self-focused aside: I graduated from OIT with a BS in Software Engineering in 2003. Yes, that's 2003. It took me only 11 years to get a 4-year degree. ;)
I've been a programmer since 1992, so about 16 years, but 11 of those I was going to school at night. Basically I worked 9a-5p and went to school 6p-10p. For the first few years I took a lot of courses, but then work happened and I tapered off to one course a term. This was fine for a long time but then credits started falling off the other side. Basically courses I took 7+ years before became obsolete. I actually lived through four Deans while I was there. I made a deal with one of them that if I taught .NET I could keep my credits longer. That let me keep taking courses while working the whole time. The result took 11 years and two schools. But now I can just say, "I've got my degree and just not mention that I got it 5 years ago. Don't tell. Lots of experience sounds better than "slow learner at school."

Whether you went to school or are self-taught, even though the Internet was originally more a place to put academic papers than a place to meet "friends", there's a LOT more really good academic information on the web than I remember. It also takes more interesting forms than just pages of class syllabi. Here's the syllabus for the CST407 class I taught in Fall of 2003.

You can learn via Googling, you can learn via Book Readin' but you can also setup a more focused "curriculum" for yourself. I know a lot of devs that I admire that do this. They'll pick a discipline, area, language, whatever, and create a mini-class for themselves. Actually that much-teased "Learn Whatever in 24 Hours" books have more structure in this way than most programming books.

These days there's all the good content at iTunesU from colleges that didn't return my calls back in my High School years. There's even 1986 video of the legendary MIT lectures "Structure and Interpretation of Computer Programs" with Hal Abelson and Gerald Jay Sussman. There's MIT's excellent OpenCourseWare Videos of the Introduction to Algorithms class up on Google Video.

Professors are creating better and better tools to visualize things, like this amazing JavaScript-based page on "Animated Sorting Algorithms" by David R. Martin. It's utterly brilliant, not just because it's a Visualizer, but because the code is in Javascript, so you're seeing it happen. It's impressive like when you're playing a video game and you discover a particularly amazing cut-scene isn't prerendered, it's rendered in-engine. (UPDATE: And it would be impressive if it were true. I'm crushed. They ARE prerendered. Well, still. It's cool. Thanks, Adam!)

I recently stumbled on Massimo Di Pierro's site and his code. He's got a CSC309/321 class that he teaches at DePaul University and has a great Python application called "Algorithms Animator." His slides on basic OOP in C++ are excellent but the Algorithms Animator is really cool. There's a video of Algorithms Animator running over at Vimeo.

He's got all sorts of common algorithms, sorts, traversals, searches, etc. The algorithms are all in src/csc321algorithms.py, like this simple binary tree example.

def isNullTree(tree):
if tree is None: return true
if len(tree)==0: return true
return false

rootnode=0
leftchild=1
rightchild=2

def BinaryTree(node,left=[],right=[]):
list=[node,left,right]
if not isNullTree(left):
left[rootnode].parent=list
if not isNullTree(right):
right[rootnode].parent=list
return list

There's also more complex ones like a Huffman encoding example. But it's not the source code that interesting, although it is. The syllabus is really detailed, with the kind of detail you really only see in academia:

Huffman Encoding Definition: A minimal variable-length character encoding based on the frequency of each character. First, each character becomes a trivial tree, with the character as the only node. The character's frequency is the tree's frequency. The two trees with the least frequencies are joined with a new root which is assigned the sum of their frequencies. This is repeated until all characters are in one tree. One code bit represents each level. Thus more frequent characters are near the root and are encoded with few bits, and rare characters are far from the root and are encoded with many bits.

The Program accepts the text to be compresses as input and produces a text report showing compression rules and compressed text. The Program also shows in an animation how the Huffman tree is built.

Huffman encoding provides an example of Greedy strategy.

What's cool about this guy's way of teaching algorithms is that his app uses animation to show the algorithm happening step by step.

For example, if I use Huffman Encoding on the string "Scott Hanselman," here's Frame 0 of the animation.

"First, each character becomes a trivial tree, with the character as the only node."

Huffman Encoding Tree

Here's Frame 15 as the the character's frequencies are counted and the tree is in the process of being built.

"One code bit represents each level. Thus more frequent characters are near the root and are encoded with few bits, and rare characters are far from the root and are encoded with many bits."

Huffman Encoding Tree (2)

Here's Frame 22 as the tree has been built out and the bit values are applied.

Huffman Encoding Tree (3)

...and the result is in the image below showing the compression rules/map and the final bits.

image

I'm not sure about you, but I'm not able to bust out a QuickSort on a whiteboard under pressure anymore (I'm old).  I found this guy's stuff to be a great algorithms refresher, and using the little Python app to explore them made it very enjoyable. I wish we had this kind of stuff when I was in school. It's kind of nice to pretend I'm back in an Algorithms class and tickle the neurons that haven't fired in a while.

Related Posts



Badge that says There's been some confusion about the size of the .NET Framework. The .NET Framework is not really a 200+ meg download. 

Which installer do I use?

Here's the whole thing in a nutshell for Developers, ISVs, and Administrators.

  • Offline Installer - One single file that can be run offline and can install the .NET Framework any system it's run on. It's complete, all platforms, installable offline.
  • Online Installer - A 2.7 meg setup program that will detect what just the files you need, then go download between 10 and 60 megs.
    • NOTE: If you're IT and inside an office, you'll want to decide if you want everyone in the office downloading .NET separately, or if you just want download it once, and have them to run it off a network share. Check out the Deployment Guide for Administrators for ways to push it out via AD or SMS.

So how big is it the .NET Framework download, really?

It depends on what you've already got installed. Here's some examples of my results using an XP SP2 machine. 

Version of
Framework installed
Download size
to get to 3.5SP1
Time to Download
(512 kbps)
None ~56 MB 15 min
2.0 ~50 MB 15 min
2.0SP1 ~33 MB 9 min
3.0SP1 ~10 MB 3 min

From a download perspective, those numbers aren't too bad. It's not nearly as bad as its been made out to be. I'm not saying this as a Microsoft apologist or paid Microsoft shill, I'm showing the numbers that I have seen in my testing. This is my opinion based on my testing.

However, as a free-micro-ISV myself, and the distributor of a .NET Client Application, namely BabySmash!, I'd like the download size to me as SMALL as possible. I've personally received the same emails many of you have - "I'd love to download your software but I don't want to download a 200 meg .NET Framework." I'd like to help change that perception to get more people to run BabySmash! and the best way to change negative perceptions is to improve reality. ;)

Online/Download Experience

The best way to get a user with reasonable Internet connectivity up on the 3.5 SP1 .NET Framework is with the 2.7 Meg "bootstrapper."  This will detect what they need and only download what they need. The worst-case scenario for a x86 machine is around 60 megs, as seen in the table above.

What's the "Client Profile?"

The Client Profile is an even smaller install option for .NET 3.5 SP1 on XP. It's small 277k bootstrapper. When it's run on a Windows XP SP2 machines with no .NET Framework installed, it will download a 28 meg payload and give you a client-specific subset of .NET 3.5.  If the Client Profile bootstrapper is run on a machine with any version of .NET on it, it'll act the same as the 3.5 SP1 web installer and detect what it needs to download, then go get it.  There's more details in the Client Profile Deployment Guide.

Ultimately, this will be the best and fastest possible way to get the .NET Framework, as it's smart on each platform. I'm going to move BabySmash to the Client Profile to get new XP customers up on .NET more than twice as fast with less than half the total download size.

The Client Profile Offline Installer (Preview) that Chris noticed was big was such because it is another example of an offline installer. It is the Client Profile Setup + the Full Installer mentioned before. Again, this particular download is totally for offline only scenarios. Unless you need a completely offline scenario, neither you nor your users need download it. The Client Profile Bootstrapper and its associated customization tools will be released soon.

Offline Experience

Now, from an offline perspective, if you're on a CD/DVD if you want to make sure that any machine you come upon will be able to get up to .NET Framework 3.5, you'll want the super offline installer. However, you can and should modify that offline installer to make it as smaller as you need. If you only support x86, then only ship those bits. Aaron Stebner points out that you can :

Extract the contents of the full install package and selectively remove payload that is not needed or supported by the scenarios that the setup that requires it supports.  I describe this option in a bit more detail in this blog post.  At a high level, this option involves identifying supported OS's and processor architectures and then selectively removing prerequisite payload from the .NET Framework 3.5 install location for platforms that the setup carrying the .NET Framework 3.5 does not plan to support.

He's basically saying for administrators and IT folks should customize the .NET Framework installer to yank stuff you don't need. This kind of customization and more is going to be easier later in September when the .NET Client Profile Configurator is released, so watch for that.

Why is that one installer so big?

That giant .NET download is for one thing - It's meant for developers or administrators who might want to redistribute a a setup that contains not just the whole of the .NET Framework, but for all possible platforms.  It has installers for x86, x64 and ia64. As mentioned above, you can customize it and make it smaller, shipping just what you need, based on your product's needs.

I've brought the total size up to bosses who care, as have many other smarter people and it's and making the installers even smaller, via separation, compression and other ideas are being actively looked at.

Windows Update

Over the next several months, machines with .NET 2.0 and up will start updating to the latest .NET 3.5SP1 using Windows Update. For ISVS (like me) this'll start to level versioning out so I'll know more about what's on the average user's machine. For example: If a machine already has .NET 3.5 on it, BabySmash is a small 1 meg download, which makes BabySmash, and me, look good.

Introducing SmallestDotNet.Com

imageLast night I made this website, SmallestDotNet.com to help out. It'll sniff your browser's UserAgent and tell you want version of .NET you have, how big the download would be to get you to .NET 3.5 and what .NET redistributable is best for you in order to minimize your download. As some newer online deployment options are released I'll update the site's sniffing to make sure that sizes and choices are is optimal.

SmallestDotNet.com also has some Javascript that you can add to your product's sites as an include, that can help let users know how big the download for .NET will be ahead of time, an lead users to the right downloads, like this:

<script src="http://www.smallestdotnet.com/smallestdotnet/javascript.ashx" type="text/javascript"></script>

It's not perfect, as it has only the UserAgent to base it's guess on. However, I've found it useful on BabySmash! and I hope you find it useful too.



I got an interesting question recently emphasis mine:

I am regular reader of you blog. I need some help in single instance winform. I have to open application when a file (.ext) is clicked (File is associated with that application like .doc with WINWORD). Application should be single instance. When I click the .ext file it should open the application with that content. If an instance is runnng it should ask the user whether you want to close this application and then open the new .ext file. Need help in C#.

Some questions are more interesting than others, but I think we've all had to solve this "Single Instance" problem over and over again over the last 15 years. I did this with a Dan Appleman VBX in Visual Basic 3 and I've seen piles of solutions with Mutexes and all sorts of overly complex dancing to solve this apparently simple problem. This is a really old technique, but three years later, there's just not enough people that know that the WindowsFormsApplicationBase class exists and has a lot of useful functionality in it.

There was an interesting thread over here about handling this. Someone asked the question and someone said "WinForms 2.0 has support for single instance apps built in." and the next guy said "Only for Visual Basic applications, though."

Microsoft.VisualBasic.dll has got to be one of the most useful standard installed parts of the .NET Framework out there. Folks are afraid to reference it from C#. It feels wrong.

Kind of like busting out with French words in the middle of English sentences, referencing Microsoft.VisualBasic.dll has that je ne sais quoi that tends to give C# folks a feeling of mal de mer but that assembly has a specific raison d'être. See? Feels wrong, but it still works. There's good stuff in Microsoft.VisualBasic.dll, and just because it isn't System.Something doesn't mean you shouldn't reference it with abandon. Go nuts.

Back to the problem. There's many examples, but the easiest one I've seen was over at OpenWinForms.com and it was written in C# referencing Microsoft.VisualBasic.dll. I've modified it here to make a single instance app that will open a text file name passed in on the command line. If you call the same application a second time, it'll take the new command line argument and load that text file in the first instance.

Launching it as "SuperSingleInstance foo.txt" from a command line...

Single Instance

Then, from the same command line, while the first one runs, launching a second "SuperSingleInstance bar.txt" from a command line. The first instance is reused, brought to the front, and gets an event letting us know someone tried to launch us and that event includes the new command line.

Single Instance (2)

The code is really cool as all the work is in WindowsFormsApplicationBase. It's a little confusing because you have to call a controller instance and tell it about your MainForm, rather than calling Application.Run(). The StartupNextInstance event is called in your first application when a second instance of your app gets fired up. It talks cross process between the new second instance and your original one and passes over the command line.

using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;

namespace SuperSingleInstance
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
string[] args = Environment.GetCommandLineArgs();
SingleInstanceController controller = new SingleInstanceController();
controller.Run(args);
}
}

public class SingleInstanceController : WindowsFormsApplicationBase
{
public SingleInstanceController()
{
IsSingleInstance = true;

StartupNextInstance += this_StartupNextInstance;
}

void this_StartupNextInstance(object sender, StartupNextInstanceEventArgs e)
{
Form1 form = MainForm as Form1; //My derived form type
form.LoadFile(e.CommandLine[1]);
}

protected override void OnCreateMainForm()
{
MainForm = new Form1();
}
}
}

The Form is trivial, just loading the text from the file into a TextBox.

using System;
using System.Windows.Forms;
using System.IO;

namespace SuperSingleInstance
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string[] args = Environment.GetCommandLineArgs();
LoadFile(args[1]);
}
public void LoadFile(string file)
{
textBox1.Text = File.ReadAllText(file);
}
}
}

There's other nice functionality in WindowsFormsApplicationBase like support for SplashScreens and network availability events. Again, check out the good stuff over at http://www.openwinforms.com/, like the Controller I used in this post.



IMG_0019I'm still using the Kindle every day for casual reading, but just now I noticed that my pile of technical books on my desk is taller than my son.

Actually, a few of these I've already read in manuscript form and I wrote either a foreword or a quote for good ones. The vast majority of the pile are books I'm currently wading through (slowly).

Here's the books I'm currently trying to read, as told by the Delicious Library application.

julyreadinglist

I've previously read Code Leader and Head First Software Development and provided quotes extolling the virtues of both, but they are such good books that I end up referring to them often enough that I haven't moved tem over to the shelf.

BTW: The Ian Griffiths/Chris Sells WPF book is in my bag. ;)

Related Links

What are you currently reading (technical books...we'll do fiction later)?



Bil Simser has just done the .NET Community a huge solid. Bil has dug up and re-released Terrarium to CodePlex wtih the intent to update it to use new language features and new usability features like ClickOnce.

If you're newish to the .NET Community (<3-5 years?) you might not have heard of Terrarium. There was a time when it was the tool for getting newbies excited about learning .NET. I showed dozens of high-school and college students how to program using Terrarium. Back at my last company one of our engineers did brown bag lunches on good bug design and ran a Terrarium Server internally.

terriarium

Terrarium hasn't been even looked at by the Microsoft SDK team in two years, as live happens, you know. Bil hunted them down, did a bunch of paperwork and it's back. You can check out the source or download the release.

You can run it alone, just a world in a box, or you can hook it up to a server and that's where it gets interesting, as your bugs all live in a connected world.

Your animals have Idle (event-based) loops that you can react to, and who amongst us hasn't wanted to write these lines of code at least once?

// Reproduce as often as possible 
if (CanReproduce)
BeginReproduction(null);

Now you have the chance.

A great lunchtime project is to get a bunch of the nerds from your company in a room, teach them Terrarium and have a battle!

Personally, I'm a lover, not a fighter, so I run away when attacked.

private void MyAnimal_Attacked(object sender, AttackedEventArgs e)
{
if (e.Attacker.IsAlive)
{
AnimalState TheAttacker = e.Attacker;

BeginDefending(TheAttacker); //defend against the attacker
WriteTrace("Run away to some random point");

int X = OrganismRandom.Next(0, WorldWidth - 1);
int Y = OrganismRandom.Next(0, WorldHeight - 1);

BeginMoving(new MovementVector(new Point(X, Y), 10));
}
}

Go check out the release of Terrarium and download the app, SDK and server. There will be more to come on Bil's Blog, I'm sure. He'll also be running a public Terrarium Server. It's exciting to see this blast from the past. Now I think it's time for me to visit a local High School Computer Science class again some lunchtime...

One of the things I think will be interesting to see, is if folks come up with better patterns for managing state within these animals. Many Terrarium animals end up with Idle loops that look like Arrow Code.

if
if
if
if
do something
endif
endif
endif
endif

This isn't nice to look at, and it would promote bad habits if it was the first kind of code someone new to programming ever saw.

The world has changed since this was released in 2002. The race is on and now I ask:

  • Who will write the first aesthetically pleasing (from a code perspective) Terrarium Animal?
  • The first F# Terrarium animal?
  • The first Ruby (DLR) Terrarium animal?
  • Boo? Nemerle? IronPython?

Enjoy!

UPDATE: I've got this running on my XP machine and my XP VMs but because of missing DirectX 6/7 DLLs I can't get it running under Vista. Possible workaround in the comments below. It'll likely be faster to just recompile it. I'll talk to Bil and see what's up.

 

Related Links



Downcasting is kind of something you usually want to avoid, but sometimes it's not easily avoided. It depends on the situation. Because it's not an idiom you'll find yourself doing every day, sometimes you'll forget to do it entirely and what you're looking for is right there under your nose.

The Problem

A buddy was trying to host the WebBrowser control in his WinForms application. It was a locally run application that was using the WebBrowser control to generate part of the UI. The user might click on a link, and you'd want to do something based on the click of an link/anchor in the HTML.

In this trivial example, I add the words "Add Comment" to a page I've navigated to within my WinForms Application.

image

First, we make some new elements within the WebBrowser control itself, like this.

HtmlElement div = webBrowser1.Document.CreateElement("div");
div.SetAttribute("style", "color:blue;");
webBrowser1.Document.Body.AppendChild(div);

HtmlElement anchor = webBrowser1.Document.CreateElement("a");
anchor.InnerText = "Add Comment";
anchor.Id = "lnkAddComment";
anchor.SetAttribute("href", "#");
anchor.Click += new HtmlElementEventHandler(doit);
div.AppendChild(anchor);

Notice that we can hook up a managed event handler to the anchor, and that the anchor's href attribute points to nothing, by setting it to "#".

anchor.Click += new HtmlElementEventHandler(doit);

My friend hooked up the event to doit() that had a standard EventHandler signature like this:

public void doit(object sender, HtmlElementEventArgs e)

You've likely seen this "object sender, SomeEventArgs e" method signature before. He started digging around in the HtmlElementEventArgs object, trying to find something he could use to known if the user had clicked on the link called lnkAddComment. He was bummed to find nothing he could use.

image 

There's a couple of thing to learn here. First, just hovering over the sender object in the debugger shows us a lot. We can see that the type of sender isn't just object, but rather System.Windows.Forms.HtmlElement. This is a CLR type, and not a JavaScript type or a type you'd know about if you were familiar with the DOM and were expecting something more DOM-like.

The DOM element in this case, is there, but it's a COM Object and is part of the IE DOM object model and you'd be better off using Visual Basic if you care deeply about getting into it as we've recently learned.

image

Downcast, Damned Spot!

However, it's an HtmlElement and it has and id property with the string "lnkAddComment," and that's useful. At this point one could down-cast it. That means, telling the compiler that we know more than it does and that we're totally sure and are willing to risk our necks.

HtmlElement foo = (HtmlElement)sender;
if (foo.Id == "lnkAddComment")
{
MessageBox.Show("woot");
}

There's some interesting things we can think about here. First, what if we're wrong? Well, bad things for one:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidCastException: Unable to cast object of type 'Something.You.Did.Not.Plan.On' to type 'System.Windows.Forms.HtmlElement'.
   at WindowsFormsApplication1.Form1.doit(Object sender, HtmlElementEventArgs e) in C:\Yay\Form1.cs:line 32

And that sucks. However, in this case we are pretty darn sure, but we should be more defensive about it.

public void doit(object sender, HtmlElementEventArgs e)
{
if (sender is HtmlElement)
{
HtmlElement foo = (HtmlElement)sender;
if (foo != null && foo.Id == "lnkAddComment")
{
MessageBox.Show("woot");
}
}
}

But that is kind of verbose, we can try a defensive cast:

HtmlElement foo = sender as HtmlElement;
if (foo != null && foo.Id == "lnkAddComment")
{
MessageBox.Show("woot");
}

In this case, if sender isn't an HtmlElement, we'll get back null. The same code in VB is pretty clear also. See the TryCast?

Public Sub doit(ByVal sender As Object, ByVal e As HtmlElementEventArgs)
Dim foo As HtmlElement = TryCast(sender,HtmlElement)
If ((Not foo Is Nothing) AndAlso (foo.Id = "lnkAddComment")) Then
MessageBox.Show("woot")
End If
End Sub

The IL (Intermediate Language) instructions are interesting also as it's asking explicitly if that object is what I think it is:

L_0001: ldarg.1 
L_0002: isinst [System.Windows.Forms]System.Windows.Forms.HtmlElement

I suppose that means I could just ask myself, but that's largely stylistic as the resulting IL is virtually the same, with the defensive cast being a simpler.

But Why the Downcast at All?

At this point you might be asking, Why did I have to downcast at all? Doesn't that mean the EventHandler pattern is lame? Maybe, but here's the thinking as described by Jeffrey Richter on page 228 of his most excellent CLR via C#, 2nd Edition (with [contextual edits and emphasis] by me so it makes sense in this post).

A lot of people wonder why the event pattern requires the sender parameter to always be of type Object. After all, since the [HtmlElement] will be the only type raising an event with a [HtmlElementEventArgs] object, it makes more sense for the callback method to be prototyped like this:

void MethodName(HtmlElement sender, HtmlElementEventArgs e);

The pattern requires the sender parameter to be of type Object mostly because of inheritance. What if [HtmlElement] were used as a base class for [DerivedHtmlElemen]? In this case, the calIback method should have the sender parameter prototyped as an [DerivedHtmlElement] instead of HtmlElement, but this can't happen because [DerivedHtmlElement] just inherited the Click event. So the code that was expecting an [DerivedHtmlElement] to raise the event must still have to cast the sender argument to an [DerivedHtmlElement]. In other words, the cast is still required, so the sender parameter might as well be typed as Object.

The next reason for typing the sender parameter as Object is just flexibility. It allows the delegate to be used by multiple types that offer an event that passes a [HtmlElementEventArgs] object. For example, a [PopHtmlElement] class could use the delegate even if this class were not derived from [HtmlElement].

One more thing: the event pattern also requires that the delegate definition and the callback method name the EventArgs-derived parameter e. The only reason for this is to add additional consistency to the pattern, making it easier for developers to learn and implement the pattern. Tools that spit out source code (such as Microsoft Visual Studio) also know to call the parameter e.

If you're interested in this kind of stuff, you should totally buy his book.

Can we avoid the cast completely?

Why did we downcast in the first place? We wanted to get ahold of the HtmlElement.Id property so we could do a string comparison in order to tell if an object is the one we're looking for. Perhaps we can check for that object's identity using something a little cleaner than a string.

In this case, since we were the ones that created the anchor in the first place we can check the "object sender" against a saved reference to our anchor by checking object identity. Are these the same two objects? Is the object I added to the object model the same one that is coming back to me as the sender parameter to this Event Handler?

HtmlElement anchor;
public void doit(object sender, HtmlElementEventArgs e)
{
if (sender.Equals(anchor))
{
MessageBox.Show("woot");
}
}

Is this a good idea? What about using == instead? In this case, I CAN use == because HtmlElement has explicitly created equality operators, so when I'm using == to compare these two instances I'm ACTUALLY calling a static op_Equality(HtmlElement, HtmlElement) on the HtmlElement type. It's static because both side might be null and I can't call methods on null instances.

HtmlElement anchor;
public void doit(object sender, HtmlElementEventArgs e)
{
if (anchor == sender)
{
MessageBox.Show("woot");
}
}

However, while operator overloading is common in C++ it's generally considered to be unnecessarily obscure in C# and moreover, you just can't count on folks to be consistent. For example, when I say == do I mean value equality or reference equality? In the case of HtmlElement they mean reference equality. In C++ an overloaded == is usually done for deep value comparisons.

I will get this warning if I try anyway:

Possible unintended reference comparison; to get a value comparison, cast the right hand side to type 'System.Windows.Forms.HtmlElement' 

I like to use Equals() myself for clarity's sake, but touché! It's going to just do this internally anyway:

public override bool Equals(object obj)
{
return (this == (obj as HtmlElement));
}

Commenter Adam makes the excellent point that using Object.ReferenceEquals is explicitly clear in expressing intent. The result would be:

public void doit(object sender, HtmlElementEventArgs e)
{
if (Object.ReferenceEquals(anchor,sender))
{
MessageBox.Show("woot");
}
}

Of course, the implementation of ReferenceEquals is just this again. ;)

public static bool ReferenceEquals(object objA, object objB)
{
return (objA == objB);
}

What's the point?

Know your options, but above all, know your intentions and make sure that the code you're writing correctly expresses your intent.



Page 1 of 14 in the Learning .NET category Next Page

Contact

Sponsors

Hosting By

On this page...

Tags

Calendar

<December 2008>
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

Archives

Google Ads