Published by

Comments

Monday, January 19, 2004 3:58 AM by Frans Bouma

# re: Towards a more functional TreeView

The real problem is under the hood. The .NET treeview is based on the asynchronous message model of win32. This means that when you do something synchronously in .NET, it is executed under the hood by sending win32 messages. This can result in serious issues.

.NET needs a synchronous, native gui library which is synchronous all the way till GDI+. The decision to base the gui glyphs on win32 stuff is perhaps based on teh fact that it would be 'faster' and 'easier to implement', but it also is the basis for most issues with .NET gui controls.
Monday, January 19, 2004 6:59 AM by anon

# re: Towards a more functional TreeView


Many great things about the windows forms treeview? It doesn't even support multiple selection natively. I think at least half of applications need that.


"Think about that for a minute, because the UI implications and different types of views start to become limitless with"

I don't know if this encourages consistent look and feel UIs, and how much this will hurt average people that are now used to the tree ctrl in windows explorer. In the corporate world, any change in the look and feel and UI costs millions in retraining. I would be willing to know how much corporate IS are spending to get people to upgrade to Windows XP, only for the required retraining. Interesting.



Monday, January 19, 2004 12:55 PM by TrackBack

# Basically, how basic can a Wizard in Windows Forms be?

Monday, January 19, 2004 1:20 PM by Raymond Chen

# re: Towards a more functional TreeView

If a single treenode could shared among multiple treeviews, what would it return for the Parent property or IsExpanded or any other property that can be different in the two treeviews.
Monday, January 19, 2004 8:01 PM by Justin Rogers

# re: Towards a more functional TreeView

I realize there are some architectural issues with my original comments, some things that need or should have been thought through more thoroughly. However, the base points shouldn't be lost. For instance:

While a basic TreeNode has properties that make it functional only when located in a single tree, there are things that could have been done to make multiple view synchronization easier. The current TreeNode can't even have an overriden Text property to allow treenodes to notify a container or factory that it's value has changed and that synchronization needs to occur.

I labeled the article, Towards a more functional TreeView for a reason. I think work can be done to make it better, and I've shown in at least one case exactly what can be done. I'll show the same in another case relatively soon, because the concept of a TreeNode factory that allows you to make *connected* copies that automatically synchronize with one another actually works. And it isn't hard to do at all.

And yes, the Parent property and IsExpanded properties between the various views might actually be different, but the Text property and any properties you add that should be synchronized could easily be.
Tuesday, January 20, 2004 4:49 AM by Darren Neimke

# re: Using the Security System for Defensive Coding

Thanks for the heads-up Justin :)
Tuesday, January 20, 2004 4:18 PM by DavidM

# re: Using Weblogs @ ASP .NET and begin friendly to the printer...

There is another problem - which I have flagged a number of times - if I view the weblogs homepage on my 1024 x 768 laptop - the navbar on the left covers half the posts - which is complete pants
Tuesday, January 20, 2004 4:39 PM by David Cumps

# re: Using Weblogs @ ASP .NET and begin friendly to the printer...

I have the same thing with the layout where a navbar is on the right, and it covers half of the text as well (i believe it was on a .Text site as well)
Wednesday, January 21, 2004 2:18 AM by Vance

# re: Using Weblogs @ ASP .NET and begin friendly to the printer...

That's one of the drawbacks to using div tags and css for positioning. Sure it makes it easier to completely change the look just by changing the stylesheet, but it tends to be somewhat quirky. Especially if you shrink the browser window and watch how things start overlapping.
Wednesday, January 21, 2004 8:18 AM by Rogelio Morrell

# re: Plug-in Framework (Part1): Marking Types for Consumption

Great article!
Wednesday, January 21, 2004 8:51 AM by Scott

# re: .Text offers excellent article hosting, but where is the RSS?

Sorry for the confusion. (agg view column)

The whole point of articles is they are not syndicated.

-Scott
Wednesday, January 21, 2004 9:14 AM by TrackBack

# First article in a series on plug-in frameworks in .NET

Wednesday, January 21, 2004 2:03 PM by chadb

# re: Plug-in Framework (Part1): Marking Types for Consumption

That's good stuff...
Friday, January 23, 2004 5:53 AM by Illumineo

# re: Revisiting the .NET Terrarium

Does it mean I'll be able to write my own agent system with the help of a Terrarium SDK, or something alike?

Friday, January 23, 2004 9:07 PM by Justin Rogers

# re: Revisiting the .NET Terrarium

Once the source code is released, you should be able to do some work and get your own agent system running.

You can also watch my series on Plug-Ins since I'll be discussing a generic framework for getting agents to run safely.
Saturday, January 24, 2004 3:22 PM by Chris McGuirk

# re: Game Engine Design Principles even apply to the most basic of games (or applications)...

If you want an example that is just a tad bit bigger than that, you should check out Axiom http://axiomengine.sf.net, which is quickly approaching a full blown .Net graphics/game engine.
Monday, January 26, 2004 9:34 PM by Matt Berther

# re: Are KB articles allowed to have poorly written code? (KB: 320348)

Justin: I'm with you on this. I cant remember how many times I've seen sample code in the MSDN library where the samples don't even compile.

When I start looking for how to do something, I look towards Google rather than the MSDN, because I tend to find a lot better samples on the web.

As a last resort, Ill use an MSDN sample, but only as that. A sample. I wont cut and paste the code into my project as is.

It's really too bad, however, it has helped me to write better API documentation. :=)
Monday, January 26, 2004 9:34 PM by Edgar Sánchez

# They definetively shouldn't

Many programmers just copy and paste Microsoft samples, if the examples do something silly as using the sa SQL Server user, the programmer will feel authorized to do the same. So please go the "best practices" way.
Tuesday, January 27, 2004 3:00 AM by Scott

# re: Are KB articles allowed to have poorly written code? (KB: 320348)

Yeah, why should Wrox books have a monopoly on errata. I think MSDN should include MORE bad code.

Now that the MVP's are allowed to write KB articles willy nilly it's just going to get worse.

Tuesday, January 27, 2004 4:28 AM by Pavel Lebedinsky

# re: Are KB articles allowed to have poorly written code? (KB: 320348)

> 2. Not checking for file existence before creating the FileStreams.

This is actually the right thing to do. FileStream is documented to throw FileNotFoundException if the file does not exist, and this is exactly what a function like FileCompare should do anyway.

You could call File.Exists() but what would you do if it returns false? Throw FileNotFoundException? Then what about the case where the file exists but you do not have access to it? Or if the file is on a remote share and there's a network problem?

File.Exists is rarely useful in library code like this FileCompare function. It lumps all possible failures into a single bool value and it is prone to race conditions.
Tuesday, January 27, 2004 4:29 AM by Simon

# re: Are KB articles allowed to have poorly written code? (KB: 320348)

The KB above is a prime example, the code they show is to improve the use of getting XML from an ADO stream. However they use a classic perf issue of concatenating strings.
This code can be improved greatly using an array, but they don't want to change the KB.

So don't do as they say or as they do!
Tuesday, January 27, 2004 9:05 AM by Paul Menefee

# re: Are KB articles allowed to have poorly written code? (KB: 320348)

I've got to defend MS here, a bit. The point of the KB it demonstrate a particular code example. We harass them all the time about being verbose and for once they cut to the chase. And just tell us what we need to know. If I'm looking for a quick solution to a particular problem I don't need to see it wrapped in a bunch of production ready code. You know, and after giving this a little more thought perhaps that's their point. If they handed programmers half-baked code that forces the programmer to take ownership and wield the code ore attuned to their application.
Tuesday, January 27, 2004 9:20 AM by Derick Bailey

# re: Are KB articles allowed to have poorly written code? (KB: 320348)

I agree with Paul Menefee.

When I'm looking up code examples in a KB article or on another website, I don't want to see it all wrapped up in best practices... I want to know how it works and why. I don't care that they missed catching a filestream exception for a null string - I know to take care of that.

If every peice of sample code was obfuscated in production ready best practices code, noone would ever learn anything because all they would have to do is cut & paste from a hundred examples and press "play" in their IDE.

I think this is more a question of properly training developers. If your coworkers or employees are dumb enough to cut & paste sample code and expect it to be production ready, maybe you owe it to them to spend some time educating them on best practices and the difference between samples / production code.
Wednesday, January 28, 2004 7:42 AM by Raymond Chen

# re: Towards a more functional TreeView

It's a question of pay-for-play. Do you want to complicate the base treeview with these features (that probably few people will actually use)? You can do a good chunk of this yourself - split your treenode into two objects, a treenode and a treenodedata. create multiple treenodes that share the same treenodedata.
Friday, January 30, 2004 5:55 PM by Justin Rogers

# re: Are KB articles allowed to have poorly written code? (KB: 320348)

Everyone focused on my assertion that file checking should exist, but that wasn't the biggest problem with the code. The largest problem is that their code paths left an open file stream if the first file opened but the second file didn't. I was pointing out ALL of the issues with the sample to demonstrate how many they were, and by pointing out that they left open file streams I also pointed out an extreme example. I honestly think you should thoroughly read the entire message before making comments on only part of it.

As it stands I'm just guessing everyone that defended MSDN here agrees that resources like file streams don't really need to be closed explicitly. And the fact that if you called this method twice before the GC kicked in you'd get an access violation on the file in question because it is already open.
Sunday, February 01, 2004 8:11 AM by TrackBack

# [Article] Game Engine Design: A series of abstractions for better engines.

Tuesday, February 03, 2004 5:29 AM by TrackBack

# Multi-Threaded applications and Abort, careful not to kill your statics...

Tuesday, February 03, 2004 8:00 PM by Brian Grunkemeyer

# re: Multi-Threaded applications and Abort, careful not to kill your statics...

Aborting your threads is one of the things that shouldn't be used by the vast majority of applications. As we started into our reliability discussions for SQL Server, we realized that a thread abort can happen basically between any two machine instructions in managed code. This means you can't guarantee you won't leak handles, and you can't guarantee that you won't corrupt static state. You could try writing finally blocks for the second case, but then we had the possibility of a host injecting a rude thread abort on your thread while running the finally, because the finally was taking too long.

(We invented SafeHandle to fix the resource leakage case, which required two additional pieces of infrastructure - critical finalizers and "must run" code, though we've replaced the second with something way better, mostly because must run didn't mean it must run at all. Ask about CER's when our beta is released, or better yet, don't.) I also had some thoughts on the static class constructor issue, but we opted not to fix them in this version due to resource constraints.

In short, if you get an asynchronous exception (ThreadAbortException, OutOfMemoryException, or StackOverflowException) anywhere within an appdomain, our recommendation in Whidbey is unload the entire appdomain. In the absense of some higher level application protocol where the caller and callee have perfect knowledge of one another and perhaps do some synchronization, you absolutely must pessimistically assume your appdomain is no longer usable.

You can read Chris Brumme's blog for some of his thoughts on Thread.Abort, but I have already given you the extraordinarily scary parts of the argument.

http://blogs.gotdotnet.com/cbrumme/PermaLink.aspx/dac5ba4a-f0c8-42bb-a5cf-097efb25d1a9

If you want to screw around with ResetAbort, well, good luck. I won't fix any bugs in the BCL w.r.t. ResetAbort any time soon. For example, if you get a Thread.Abort while removing an item from the middle of an ArrayList in just the right spot, you'll remove the LAST element from the ArrayList. After looking at this problem in great detail, we realized thread abort makes reliable code nearly impossible to write, if not impossible. You need our new Whidbey features to make this problem tractable.

Attempting to build anything reliable on top of Thread.Abort in anything pre-Whidbey (short of using process recycling) is crazy, and in Whidbey it will be difficult, but possible.
Tuesday, February 03, 2004 9:14 PM by Brian Grunkemeyer

# re: Static Constructors and Plug-In Security...

1) System.CompilerServices.RuntimeHelpers.RunClassConstructor(RuntimeTypeHandle). It will guarantee that the class constructor has been called, or it will throw some sort of exception.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemRuntimeCompilerServicesRuntimeHelpersClassRunClassConstructorTopic.asp

2) No. See another comment of mine on your blog about why you don't want to use Thread.Abort.
Tuesday, February 03, 2004 9:14 PM by Justin Rogers

# re: Multi-Threaded applications and Abort, careful not to kill your statics...

So the only reliable way to run arbitrary code that may have need of being terminated before it is done, is to make liberal use of AppDomains? I realize there is a good deal of work going into cross AppDomain marshalling so the speed issues might be easy enough to overcome at this point.

We overcame many of these issues in Terrarium by hacking around a lot of potential problems and ensuring the code didn't have specific constructs. These included static fields, static methods, any static access whatsoever, making sure code has empty constructors, and preventing finally blocks. The concept being that since this was arbitrary code, it wouldn't need access to these advanced features. Unfortunately, there is no method to do this without an IL grep. There are no run-time features or enhanced security features to apply to code being loaded into an AppDomain that says a) this code can't access statics or b) this code can't use finally blocks.

Now that AppDomain's might turn out to be the only method for reliable secure plug-in usage, I'll go down that path.
Tuesday, February 03, 2004 9:18 PM by Brian Grunkemeyer

# re: Finalizers and the nasty stuff plug-ins can do if they want to...

There isn't much you can do to stop this. GC.ReRegisterForFinale does not have any security permissions on it, not even any host protection permission in our Whidbey builds.

One thing you could do is write your own "IL verifier", where you only load code that meets your programming model constraints. IE, disallow all static variables, or reject any classes that provide a finalizer (noting that Object of course has a finalizer - just test this rule on some conforming types).
Tuesday, February 03, 2004 9:30 PM by Brian Grunkemeyer

# re: Multi-Threaded applications and Abort, careful not to kill your statics...

Our reliability story for managed stored procedures in SQL Server is hinged on being able to cleanly recycle an appdomain if any of the threads (or managed threads running on fibers within that AD) go awry. With Whidbey features like SafeHandle and some exceedingly pervasive out of memory cleanup, we can ensure we don't leak OS resources in this case. If it's good enough for SQL Server, it's probably good enough for you.

There are some guidelines for writing reliable managed code in an appdomain-recycling model like this. I'm not sure we can make them public at this point, but keep an eye out for them in our Whidbey beta release. The most notable thing you should know is lock(typeof(Foo)) is bad, for all Foo. Don't do it. An upcoming FxCop release should have some reliability rules as well that point out some of this information.

BTW, SQL will also use some kind of IL verifier to enforce programming model constraints on stored procedures. Also, check out host protection permission. If you're willing to go all-out and host the CLR in-process using our complex hosting API's, there are ways you can add link demands that not even fully trusted code will be able to satisfy. Unfortunately for you, the HostProtectionAttribute can only be applied to methods like Environment.Exit and Monitor.Enter, and is not useful for problems like "does my class have a .cctor?" Hence, a custom IL verifier.
Tuesday, February 03, 2004 9:57 PM by Brian Grunkemeyer

# re: Multi-Threaded applications and Abort, careful not to kill your statics...

BTW, here's Chris's explanation of our reliability story, complete with a disclaimer against being prematurely slash-dotted. Read this if you want a pretty in-depth understanding of where we are on reliability, and my comments above are in essence added material. If you want more, come work on the CLR team.

http://blogs.msdn.com/cbrumme/archive/2003/06/23/51482.aspx
Saturday, February 07, 2004 1:42 AM by TrackBack

# Preamble to the Plug-In Framework series of articles...

Saturday, February 07, 2004 4:53 AM by Sami Vaaraniemi

# re: Plug-in Framework (Part1): Marking Types for Consumption

Good article!

There is another fairly common approach to plugin frameworks that I think deserves to be mentioned. You can use a sort of a catalogue service (or a configuration file) that returns a list of assembly locations and types, for example: "http://company1/plugins/plugin1.dll, Company1.Plugin1". This bypasses the need for marking types because once the loader has this list it already knows which types to load.

Doing this securely is another story though - you would probably want to require all remotely loaded plugins to be signed.
Saturday, February 07, 2004 7:48 AM by Stefán Jökull

# re: Allegiance Source Code vs Quake II, you decide...

I'd definately go for Quake II. It's a lot more popular and is still played heavily. Being able to do some improvements as well would be nice to show how easy it is using C#.

By the way, how have you been converting it. Have you been doing a straight conversion or have you been making it more object oriented then originally?
Saturday, February 07, 2004 9:28 AM by OmegaSupreme

# re: Allegiance Source Code vs Quake II, you decide...

I vote quake because its so cool. If people see a classic fps in c# they're gonna be impressed.
Saturday, February 07, 2004 11:37 AM by Dan Bright

# re: Allegiance Source Code vs Quake II, you decide...

I vote Q2 also. You can never go wrong with an old standard like that.

Saturday, February 07, 2004 1:36 PM by Shannon J Hager

# re: Allegiance Source Code vs Quake II, you decide...

I would say Allegiance for all the reasons above. "Classic"? "Old standard"? That's going to impress someone? I've seen the old standards: tetris, pacman, etc, ported to C#. If you want to show the power of C# then show a great modern game, not an old standard because it is easier. Going the easy route makes me think that C# can't handle a real modern game.
Saturday, February 07, 2004 10:43 PM by Justin Rogers

# re: Allegiance Source Code vs Quake II, you decide...

To answer everyone's questions:

This is not a straight conversion, this is an object oriented rearchitecture of the original game. There are quite a few areas were it makes sense and some where it has appeared pretty stupid to do this, but hopefully the end result will be a better demonstration of .NET's power than a simple port.

I love the fact that it is an FPS. Would be the first fully managed FPS? Quake .NET?

Shannon makes some good points too though. The Allegiance codebase is much larger and more complex than the Q2 codebase. The time to conversion would be a bit longer, but the Allegiance code makes use of more recent techniques that more properly translate into fully object oriented code than does the Q2 code.

The biggest addition to the Q2 code will be an MDX for DX9 display filter. Rather than using the crappy old OGL or Software Rasterizers we'll go straight out to MDX. Should provide a huge frame-rate increase (over 250 FPS)
Sunday, February 08, 2004 7:03 AM by Nicko

# re: Allegiance Source Code vs Quake II, you decide...

Vertigo Software have already ported Quake II to the .net runtime using Managed C++

See http://www.vertigosoftware.com/Quake2.htm

This was linked from the msdn.microsoft.com home page for a while.

Looks like you are porting to C# which is a bit different, but I doubt that if you just port Quake II it will have that much of an impact, so I suggest that you port the Allegiance engine.
Sunday, February 08, 2004 9:11 PM by Justin Rogers

# re: Allegiance Source Code vs Quake II, you decide...

Vertigo software's port of the Quake II engine is kind of a joke. Quake II can be recompiled onto the .NET Framework using managed code within a few hours, I know, because I've done that already.

The upgrades they did are also a joke using overlaid forms.

This is a true port, with emphasis on redesigning the engine to work at maximum potential under the managed run-time. It also emphasizes a Managed DirectX rendering layer, which I pointed out in previous comments. I don't see how a C# application running at twice the framerate of the C++ version of the application is not much of an impact. I also don't see how the first FPS running fully managed using C# isn't much of an impact.
Sunday, February 08, 2004 9:13 PM by Shannon J Hager

# re: Allegiance Source Code vs Quake II, you decide...

Either way, Justin, keep us posted.
Monday, February 09, 2004 1:53 AM by TrackBack

# Plug-In Framework (Part 1), Update covering configuration based enumeration

Monday, February 09, 2004 5:02 AM by stefan demetz

# re: Plug-in Framework (Part1): Marking Types for Consumption

Excellent
Monday, February 09, 2004 9:23 PM by Rick Ross

# re: Extending the security system with new permissions...

>Do CAS permissions have to be located in strongly named assemblies?

Yes. Any security classes used to extend CAS must be configured as a fully trusted assembly.
Tuesday, February 10, 2004 4:34 PM by Brian Grunkemeyer

# re: Preamble to the Plug-In Framework series of articles...

Look at the CLR's host protection permission in Whidbey. You'll see it labeled as "HPA's" often, since you can only apply this permission by using the HostPermissionAttribute. This allows the host to do two things:

1) Disable user code from calling certain API's for programming model reasons
2) Disable even fully trusted code (like System.dll) from calling certain API's for reliability reasons

Unfortunately, a method or property must be explicitly marked with an HPA for this to take effect. So you can't make an arbitrary set of programming model restrictions, but only choose whether to restrict access along some of the axes we've provided (such as self-affecting threading vs. external threading, synchronization, UI, etc.) Hopefully that's somewhat interesting.
Thursday, February 12, 2004 3:34 AM by Stephane Rodriguez

# re: On the new Longhorn SDK, a designer asks, "Does size matter"...


Reindexing MSDN content usually takes several minutes. Are you ready to pay for this every other week?
Thursday, February 12, 2004 5:21 AM by Justin Rogers

# re: On the new Longhorn SDK, a designer asks, "Does size matter"...

I'm not suggesting the re-indexing of MSDN content. I'm suggesting that the very latest index files be present on my machine based on an automatic from-web update straight from Microsoft. Worried about long downloads, then use a diff merge instead of downloading the entire thing each time.

The indexes will only change when new content is added or old content is modified. I don't think the churn will be enough that new index downloads would be an issue.

Don't use the existing system as an example, it isn't nearly the system that would catch my attention for both performance and extensibility features.
Thursday, February 12, 2004 6:06 PM by stefan demetz

# re: Using the Security System for Defensive Coding

Friday, February 13, 2004 10:03 PM by TrackBack

# PermitOnly is excellent for security, but can be a bane to programming..., enter PermissionSet

Friday, February 13, 2004 11:39 PM by Shannon J Hager

# re: Movie recommendations, what in the heck are they thinking...

Do you want to help make a better recommendation system? I've had one rolling around in my head for a few weeks, if you're interested in hearing about it, shoot me an email via the contact form on my blog.
Saturday, February 14, 2004 12:25 AM by Jason Mauss

# re: Movie recommendations, what in the heck are they thinking...

I've "rated" like over 300 movies on NetFlix, thinking it would produce better reccomendations for me and it still doesn't even come close. I've resorted to clicking on the actors names on the movie detail pages to get a list of films for an actor, then scanning those for the actor's latest films.
Saturday, February 14, 2004 3:51 PM by John

# re: Movie recommendations, what in the heck are they thinking...

Certainly it's not ideal. Over time it does start to help. I've noticed that the recommendations come in different places by different criteria, and ultimately you start feeling, "I've seen all this!" but give it a few weeks and more recommendations and suddenly you find listing you never saw before. Or maybe Netflix expanded... I just know it's reasonably effective, though not ideal.
Sunday, February 15, 2004 5:49 AM by TrackBack

# MatchSparse? An implementation detail.

Sunday, February 15, 2004 5:53 AM by TrackBack

# MatchSparse? An implementation detail.

Tuesday, February 17, 2004 4:06 AM by stefan demetz

# re: Needed a Crc32 class for some code, figured I'd share with the rest of you.

thanks
Tuesday, February 17, 2004 6:49 AM by Darren Neimke

# re: BinaryFormatter can hang within modified stream?

Justin... did you find a suitable hack, err, *workaround* :-) for this?
Tuesday, February 17, 2004 10:24 AM by bilbo

# re: Using the FilePlanet.com model with regards to Web Services and availability...

perhaps look at existing web service models for reference. For instance, eBay's web service has different payment subscription levels. Google limits the number of times you can query the service, etc. I'm having the same problems figuring out how I want to offer my web service. Free to the public hurts my pocket book!
Wednesday, February 18, 2004 3:48 AM by Justin Rogers

# re: BinaryFormatter can hang within modified stream?

I never did work through to the root cause, reason being, I don't have access to the code for the BinaryFormatter itself to figure out why changing the length of a type name in the stream would cause such a hang.

However, examining the types involved, it would take a good deal of inspection through IL in order to get to the root of the problem. The BinaryFormatter appears to be one of the more complex pieces of code present in the framework.

Maybe I'll head on over to the Rotor source in the next week and use that to discover the root issue.
Wednesday, February 18, 2004 5:50 AM by Ricky Dhatt

# re: Causal Gamers, Women over 40, (aka PopCap games and MS Gaming Zone ;-)

Your "unhackable" comment caught my eye. My girlfriend and her friends all play The Sims. Now they all use the cheat to get unlimited cash so they can build the home exactly the way they want. This drives me nuts, not enduring the "challenge" of the game; but she's perfectly content with it.
Wednesday, February 18, 2004 7:21 PM by Jason Olson

# re: Allegiance Source Code vs Quake II, you decide...

Hey Justin, I would vote for Quake 2.
Wednesday, February 18, 2004 8:43 PM by Justin Rogers

# re: Allegiance Source Code vs Quake II, you decide...

Yep, I'm still working on the Quake II source code. Most of the process is done. Rewriting the graphics engine right now is the largest chore because of the GL processes that don't translate well into DirectX 9. I'm also taking the time to improve the code-base using modern techniques and batching.

Stay tuned, because this is going to be one hell of a sample.

(latest development: Adding the ability to import HL models ;-)
Thursday, February 19, 2004 1:10 AM by Darren Neimke

# re: BinaryFormatter can hang within modified stream?

Cool, thanks Justin. I'll check back here from time-to-time as I remember to but, if you do find out anything interesting inside the next 6 months (say), and you remember, can you give me a ping?

Cheers :-)
Thursday, February 19, 2004 5:26 AM by Darren Neimke

# re: BinaryFormatter can hang within modified stream?

got it! thanks mate :-)
Thursday, February 19, 2004 5:32 AM by Frans Bouma

# re: Follow up to corrupted binary stream in BinaryFormatter causing OOM exception...

Aren't string in .NET Unicoded?
Thursday, February 19, 2004 5:33 AM by Justin Rogers

# re: Follow up to corrupted binary stream in BinaryFormatter causing OOM exception...

They appear to be UTF8 encoded as per the default BinaryWriter would do.
Thursday, February 19, 2004 8:12 AM by TrackBack

# Follow up to corrupted binary stream in BinaryFormatter causing OOM exception...

Thursday, February 19, 2004 8:31 AM by TrackBack

# Follow up to corrupted binary stream in BinaryFormatter causing OOM exception...

Thursday, February 19, 2004 8:41 AM by Ken Cox [MVP - ASP.NET]

# re: Pointing out the Control Gallery's...

Hi Justin,

Good timing! I've been doing some housekeeping in the Control Gallery this week and thinking that it should be offering new items and categories as RSS feeds. That would be a valuable addition. (There are also some small formatting bugs that need swatting.)

The problem is that we need someone who knows the existing code (hint, hint) and who could implement these few changes. (Okay, I'm lame in C#.)

The best course would be to contact Rob Howard at Microsoft about getting private access to the current code to make the changes.

Thursday, February 19, 2004 9:46 AM by TrackBack

# Final complaints about BinaryFormatter and the persistence format...

Thursday, February 19, 2004 9:46 AM by TrackBack

# Final complaints about BinaryFormatter and the persistence format...

Thursday, February 19, 2004 3:07 PM by Bill

# re: Are KB articles allowed to have poorly written code? (KB: 320348)

<<
Should KB articles that attempt to create non-existent technology do so with the mindset of LCS...
>>

In my opinion, kb articles, msdn docs and all of the sample code need to demonstrate their associated concepts. Production quality code is, in my opinion, not what these things should be expected to provide. They're not supposed to be teaching people how to write code. They aren't code repositories.

<<
This is actually the right thing to do.
>>

I disagree. The "right thing" to do is to validate input.

<<
As it stands I'm just guessing everyone that defended MSDN here agrees that resources like file streams don't really need...
>>

Your logic is flawed.
Friday, February 20, 2004 5:23 AM by Darren Neimke

# re: An algorithm puzzle from a rotor code examination. Weigh in your thoughts...

I really don't have much to add in terms of your questions but, it always interests me to see people who are concerned enough to put conditions at the bottom of loop structures like that (i.e. do...while's as opposed to while loops). It's a good reminder that there's more than one way to do stuff but, left unchecked it opens up another possibility for failure.
Friday, February 20, 2004 5:31 AM by Justin Rogers

# re: An algorithm puzzle from a rotor code examination. Weigh in your thoughts...

For the most part, this is straight out of the rotor code, except for our updates. I have to say, putting the condition at the end of the loop here is IMO the right thing to do. It makes the code much more elegant than it would otherwise be.

Now, would I have written the loop the same way had I not been looking at the rotor code when writing my method? Maybe, maybe not. It would certainly have taken me some thought to come to this method, because it is not an oft used method for me.
Friday, February 20, 2004 7:00 AM by Darren Neimke

# re: An algorithm puzzle from a rotor code examination. Weigh in your thoughts...

So, what does:

( ( _b & 0x80 ) != 0 )

.. test for? As in, what is 0x80?
Friday, February 20, 2004 7:08 AM by Justin Rogers

# re: An algorithm puzzle from a rotor code examination. Weigh in your thoughts...

_b & 0x80 tests the highest bit of the byte.

So basically:
0x80 translates to 10000000 binary

The way 7 bit encoded integers work, is this. Read a byte, take the bottom 7 bits and add it to your accumulator, shifting if necessary (by a multiple of 7). Then check the highest bit, or the 8th bit, and see if it is set. If it is set, then we aren't done yet. We need to read another byte from the stream and continue the decoding process.
Friday, February 20, 2004 12:56 PM by gilad g

# re: Awesome Windows Forms message pump trick...

...And with the power of anon. methods in C# Whidbey, there won't be any need for pre-defining a "Method Invoker" :)
Friday, February 20, 2004 1:31 PM by Bill

# re: An algorithm puzzle from a rotor code examination. Weigh in your thoughts...

<<
do...while's as opposed to while loops
>>

In the Write... code a while loop is used because you don't always want to enter the loop. In the Read... code, a do loop is used because you always want to go through the loop at least once. You could re-code each method to use the other construct, but you'd have to add more code to handle special cases.

<<
left unchecked it opens up another possibility for failure.
>>

Not any more than other constructs. Unless I'm missing something about do..while loops.
Saturday, February 21, 2004 10:03 AM by TrackBack

# Answers to the rotor code algorithm puzzle...

Monday, February 23, 2004 10:58 AM by Jerry Dennany

# re: I promised I would talk a bit about Terrarium, so here goes...

Ah, but it isn't boring. Many, many applications make the same mistakes about writing to the current directory, and you help bring focus to this issue.
Monday, February 23, 2004 3:16 PM by Justin Rogers

# re: I promised I would talk a bit about Terrarium, so here goes...

Yes, most applications do make the mistake of using their own directory as a stomping ground for file IO code. It is hard to decide how to implement your file IO restrictions though, and I think this will be the interesting facet of the Terrarium changes. Currently the code changes just do the right thing, however, there are some sticky issues with when we really do need to write files in user selectable locations.

I'm thinking a change to our permissions code to deny File IO at a very early stage in the loading process might be worth looking into. I'll definitely blog about that kind of change because it starts to get interesting.
Tuesday, February 24, 2004 2:34 AM by Thomas Tomiczek

# re: Rotor FUBAR of the day: Why did IPAddress take a public long constructor?

One World:

CLS.

CLS does not allow usigned variables. So UInt (which IPV4 ACTUALLY is does not work). So - in rder to handle all "official" representations of IP in single int form, they had to make the variable an Int64.

You get the same thing with port numbers on sockets, interesting enough, although there they do not get into compatibility mode. he IpEndPoint has an int as port number - interesting in that port numbers run up 65536 and int is 32 bits. But heck, then: CLS does not allow an ushort to be used :-)
Friday, February 27, 2004 8:38 PM by Justin Rogers

# re: Rotor FUBAR of the day: Why did IPAddress take a public long constructor?

Darn, sorry for the long delay in reply, the flu seems to have found me.

This is a perfect response, since it really points out why certain designs were adopted. I'm glad someone had the insight to point this out, since I probably would have overlooked this.

Why? Well, because having used sockets for so long, the sign of a 32-bit integer has never really mattered. Behind the scenes a negative integer is simply mapped to an appropriate IP, and you never find yourself typing the integer format of an IP address anyway.

I think this FUBAR has been reversed and I'll graciously accept that the *right thing* was done.
Sunday, February 29, 2004 4:15 AM by Kartal Guner

# re: My god what was I thinking, using StringCollection over ArrayList?

I assumed the same thing. Good to know this though. I haven't gotten to the point where I am trying to fine tune the performance yet. The StringCollection has a Contains function which is nice though.
Sunday, February 29, 2004 5:36 AM by Justin Rogers

# re: My god what was I thinking, using StringCollection over ArrayList?

Contains is part of IList, and so ArrayList also has a Contains method. It uses an Equals override to determine equality.

if (item.Equals(_items[i]))

For strings, Equals is an internal call. It looks something like the following code which is a basic C++ string comparision function, with the exception of there being a couple of additional items to handle managed specifics.

//
//
// COMPARATORS
//
//
bool WcharCompareHelper (STRINGREF thisStr, STRINGREF valueStr)
{
DWORD *thisChars, *valueChars;
int thisLength, valueLength;

//Get all of our required data.
RefInterpretGetStringValuesDangerousForGC(thisStr, (WCHAR**)&thisChars, &thisLength);
RefInterpretGetStringValuesDangerousForGC(valueStr, (WCHAR**)&valueChars, &valueLength);

//If they're different lengths, they're not an exact match.
if (thisLength!=valueLength) {
return false;
}

// Loop comparing a DWORD (2 WCHARs) at a time.
while ((thisLength -= 2) >= 0)
{
if (*thisChars != *valueChars)
return false;
++thisChars;
++valueChars;
}

// Handle an extra WCHAR.
if (thisLength == -1)
return (*((WCHAR *) thisChars) == *((WCHAR *) valueChars));

return true;
}
Monday, March 01, 2004 2:02 AM by TrackBack

# Game design books focused on non *core* markets, a short resource list...

Tuesday, March 02, 2004 8:27 PM by Addy Santo

# re: Trials and Tribulations of UI design: An examination of the Focus SVT dashboard...

A friend of mine got a panicky call from his wife a while back, saying "I'm in my car and a red icon just came on with a picture of an explosion with a mushroom cloud. I stopped on the side of the road and I'm afraid to turn the engine back on"

A quick phone consultation with the dealership revealed that the icon she was referring to was "low windshield fluid" and the mushroom cloud was really an attempt to show fluid spraying on the windshield (think of a whale-blowing-air caricature)

Friday, March 05, 2004 1:19 AM by TrackBack

# re: New Terrarium UI

Saturday, March 06, 2004 12:55 AM by TrackBack

# String::Join vs StringBuilder::Append vs StringBuilder::Append /w capacity...

Sunday, March 07, 2004 1:15 AM by Richard Tallent

# re: Doing some perf testing, String::Join vs StringBuilder::Append...

This may be a bit unfair to StringBuilder: after all, it is dynamically resizing its internal structure each time you double the number of characters after 16, whereas your Array has already been instatiated, sized, and populated.

Better apples to apples:
1. Use StringBuilder.EnsureCapacity to overcome the advantage Array has by having a preset allocated size.
2. Move the starting time for Array to above the For loop to remove the bias of overhead from the loop and population effort.

Notwithstanding the above, you've made a good point: if you already have an array, String.Join makes a lot more sense than iterating through the array again and copying it to a StringBuilder.
Sunday, March 07, 2004 2:56 AM by Justin Rogers

# re: Doing some perf testing, String::Join vs StringBuilder::Append...

I accounted for the resize in a follow-up post. If you click on the trackback link for the first comment you'll see the follow-up. While there is stil some incorrect information in the follow-up regarding string interning which turns out not to be happening at all, the timing values are spot on and shows String::Join to be only 25% faster than StringBuilder::Append when using capacity planning.
Saturday, March 13, 2004 8:57 AM by Winnifred Alberts

# re: I promised I would talk a bit about Terrarium, so here goes...

Is there any way you can give us eager little coders an approximate date as to when the terrarium source code is going to be released? I am so excited about the prospects of getting my hands on the code! :-)
Saturday, March 13, 2004 8:08 PM by Justin Rogers

# re: I promised I would talk a bit about Terrarium, so here goes...

Eager coders should take this to heart... Soon. And this time we mean it, and are very close.

Since I won't tell you when I can tell you a little more about what. The Terrarium source release is going to be a true experience. Starting with the hopefully flawless and easy to use install process of all Terrarium components down to the refined look and bug fixes to the game play that have been plaguing some developers.

The source code and documentation are going to be indispensable for reference when programming similar applications in the future. In other words, it is worth a small wait and a bit of uncertainty ;-)
Saturday, March 13, 2004 8:14 PM by Koji Ishii

# re: String::Join vs StringBuilder::Append vs StringBuilder::Append /w capacity...

I don't remember how I get this, but if I remember correctly, what string.Join does is:
1. Create a StringBuilder with capacity strings.Length * 16 (this 16 is a fixed number)
2. call sb.Append
This explains why your SBWithCapacity is a bit slower than string.Join, because string.Join doesn't iterate through the array to detect capacity of StringBuilder.
string.Join is faster if average of the length of the strings are less than 16, but I guess yours is faster if longer than that.
Saturday, March 13, 2004 9:08 PM by Justin Rogers

# re: String::Join vs StringBuilder::Append vs StringBuilder::Append /w capacity...

This is incorrect, String::Join as defined inside of the rotor code-base, iterates and creates a precisely sized string. It does not use StringBuilder internally.

The answer is inside of clr\src\vm\comstring.cpp as ConcatenateJoinHelperArray which is called by String::Join to help stitch the string together.

And here is the code and comments that defines precisely that String::Join allocates a perfectly sized memory area for the concatenation of the strings:

//Figure out the total length of the strings in (*value).
elemCount = startIndex + count;
for (numElems=startIndex; numElems<elemCount; numElems++) {
if (((*value)->m_Array[numElems])!=NULL) {
newLength+=((STRINGREF)((*value)->m_Array[numElems]))->GetStringLength();
}
}
numElems=count;

//Add enough room for the joiner.
joinerLength = (*joiner)->GetStringLength();
newLength += (numElems-1) * joinerLength;
Sunday, March 14, 2004 7:42 PM by Darren Neimke

# re: Testing your tests. Ensuring test validity and preventing common mistakes...

Justin, thanks for this post it cleared up a lot of things for me. One thing though - just for accuracy's sake - when you say:

"In Darren's case he thought he was fixing the problem and that the 30 was the real result he was looking for and that the 4000 had to be inherently flawed"

That's not quite right. I blog'ged them because I knew something was wrong somewhere but just didn't really know where/how to look for it. I actually posted a copy off to the VB guys as well just for them to look at.

Another quirk is that I knew that what I was testing probably wasn't functionally == I was just looking for the quickest way to break strings into smaller pieces (for example I'm sure that my Regex.Split tests are not == to String::Split()).

The biggest surprise for me so far is that the String::Split semantics is different to what I had pre-supposed; and you're right, I would have picked that up if I'd checked the outputs.

Thanks again for taking the time to look into this stuff!
Sunday, March 14, 2004 8:29 PM by Justin Rogers

# re: Testing your tests. Ensuring test validity and preventing common mistakes...

Well, even though you weren't thinking that way, you still made a great example ;-) A lot of people do think that way, especially when the initial tests were showing such a huge performance issue with the VB version.

Many developers would have assumed they had the *fix* after the changes you made were implemented because it appears to rationalize the results. I mean, 4000 milliseconds is a long time compared to the results of the other tests you ran.

As for the String::Split semantics, the only way to get something functionally equivalent that splits on a string rather than a character basis, is to code your own (hence the VB guys Split function implementation). However, their method isn't truly optimal, and I think you could write a faster Split() function implementation. I might just try this.
Sunday, March 14, 2004 9:40 PM by TrackBack

# Testing your tests. Ensuring test validity and preventing common mistakes...

Sunday, March 14, 2004 9:40 PM by TrackBack

# Testing your tests. Ensuring test validity and preventing common mistakes...

Sunday, March 14, 2004 9:42 PM by TrackBack

# Testing your tests. Ensuring test validity and preventing common mistakes...

Sunday, March 14, 2004 9:42 PM by TrackBack

# Testing your tests. Ensuring test validity and preventing common mistakes...

Monday, March 15, 2004 12:24 AM by TrackBack

# re: String::Split - unexpected behaviour?

Sunday, March 21, 2004 4:46 AM by Darren Neimke

# re: Want faster regular expressions? Maybe you should think about that IgnoreCase option...

Justin, just for laughs can you show the metrics for a test where you *do* the ToLower() on the input string. In other words:

private static Regex ignoreCase = new Regex("hello".ToLower(new CultureInfo("en-US", false)), RegexOptions.Compiled);

One of the things that interested me while peeking at Rotor source is that, one of the overloads of AddConcatenate takes a third boolean parameter which stops the ToLower() call from happening when doing a replacement - even if using IgnoreCase. I couldn't really work that one out.
Sunday, March 21, 2004 5:35 AM by Frans Bouma

# re: Performance: If vs Switch in what we might call an extended usage scenario?

Actually the compiler optimizes the switch statement: if it can, it will create a hashtable with name-value pairs. The 'name' part is the value used in the code for the case (such as case "Foo"), the value is the value used in hte optimized case (such as case 4). The hashtable is static.

With a few iterations, this is slower, as it will have to build up the hashtable. For more iterations this is very fast. Check a release build compile of a switch case with strings in reflector :)
Sunday, March 21, 2004 5:39 AM by Darren Neimke

# re: Want faster regular expressions? Maybe you should think about that IgnoreCase option...

BTW... good luck digging through the source to see what IL is produced; have you ever seen the stuff which is Emit'ted from the RegexCompiler module ? :-)
Sunday, March 21, 2004 5:59 AM by Justin Rogers

# re: Want faster regular expressions? Maybe you should think about that IgnoreCase option...

I know why the one is faster versus the other now... I'm pretty adept at going through Rotor ;-)

A character class uses a specialized binary search algorithm across a specialized string of characters that exists as a result of RegexCharClass. This becomes a single call within the compiled binary into a helper function.

With an alternation construct, a butt-load of instructions are emitted that trace each path in the alternation and backtrack if necessary to start on the next item. These are called groups and use something called the grouping stack.

At least this is what I'm gathering right now. I'll probably keep doing work on the source, however, running simulations seems to be turning out better numerical results, even if those results aren't being firmly rooted.
Sunday, March 21, 2004 6:31 AM by Justin Rogers

# re: Want faster regular expressions? Maybe you should think about that IgnoreCase option...

Here are the results of doing a ToLower before calling the expression:

C:\Projects\CSharp\Utilities\PoliCheck>WordIgnoreCase.exe
Ignore Case By ToLower Sanity Check
True
End Ignore Case By ToLower Sanity Check

Ignore Case Sanity Check
True
End Ignore Case Sanity Check

Explicit Case Sanity Check
True
End Explicit Case Sanity Check

Character Class Sanity Check
True
End Character Class Sanity Check

Ignore Case By ToLower, 00:00:02.8440896
Ignore Case, 00:00:01.7625344
Explicit Case, 00:00:01.2518000
Character Class, 00:00:01.1716848
Sunday, March 21, 2004 7:13 AM by Justin Rogers

# re: Performance: If vs Switch in what we might call an extended usage scenario?

However, I wasn't usi