The FBI raid.
The CEO who, on his last day, managed to cram 1 executive leather chair, 2 desktop computers, a file cabinet, and a bookshelf into a 2 door BMW.
The intern who wore pink teddy bear clips in his beard.
The CEO who painted his toenails the company colors.
The CFO who was amazed to see how Excel could recalculate cell C3 based on the contents of cell C1.
The CTO who enlisted the aid of a software developer in chasing down escaped chickens back at the farm.
What it is like to show up for work at a new company and see the office furniture from my last company being delivered by tractor trailer.
Why I should not be given the opportunity to take the helm of a yacht for any length of time.
What it is like to have a practicing gastroenterologist at the office part time and how this leads to errant phone calls from people describing the odd color of their stool and demanding advice on what to do about it.
The vice president of global sales who drove a different vehicle to work each day yet never made a sale, and why I think this is because he wore Hawaiian shirts and Nikes during appointments at Fortune 50 companies.
Last but not least: Why engineers should not be required to move office furniture when moving to a new building.
First, some background. There are two versions of the garbage collector for .NET. The garbage collector optimized for multi-processor machines (packaged in MSCorSvr.dll), and the workstation garbage collector (packaged in MsCorWks.dll). I can see who is running the workstation garbage collector on a Win2003 machine using tasklist from the command line:
tasklist /m mscorwks.dll Image Name PID Modules ========================= ====== ================== OUTLOOK.EXE 3352 mscorwks.dll mmc.exe 2084 mscorwks.dll w3wp.exe 3436 mscorwks.dll
One of the comments suggested going into the .NET Configuration 1.1 MMC in Administrative Tools, right clicking on My Computer, and setting the garbage collection mode to “Run in foreground for server applications”.
This struck me as odd, because in doing some review work for the Performance and Scalability Guide I found out that choosing the garbage collector implementation with a .config file setting was not going to be a runtime feature until the Whidbey timeframe. I tried this configuration option and reset IIS. After hitting a local web application and running taskmgr again my ASP.NET worker process (W3WP.EXE) was still showing mscorwks.dll loaded, not mscorsvr.dll
After a little more digging I discovered the MMC toggles the gcConcurrent element in machine.config:
<runtime> ... <gcConcurrent enabled="false" /> </runtime>
It turns out the gcConcurrent setting does not change which garbage collector loads. gcConcurrent only has an impact on the workstation (MsCorWks.dll) implementation of the garbage collector (it is effectively ignored by the server implementation), and furthermore only changes the GC behavior on multiprocessor machines.
With the setting enabled the garbage collector uses an additional thread to build a graph of unreachable objects. The rule of thumb is, gcConcurrent=”true” (default setting) will provide for a more responsive application, but can also let the working set (memory usage) grow larger. You’d have to carefully test an application to see if disabling gcConcurrent actually helps an application’s performance or memory usage. The most detailed source of information I’ve found in one place on this subject is Jeffrey Richter’s book.
<SARCASM>To turn this into a spirited debate, I want to point out that developers who use MsCorSvr.dll on average earn 26% more than developers using MsCorWks.dll. </SARCASM>
Honestly, with all the cycles the .NET community burns on language debates, we could have built another language.
Hashtable lastNames = new Hashtable(); lastNames.Add("Beatrice", "Arthur"); lastNames.Add("Lucille", "Ball"); object name = lastNames["Audrey"]; if (name == null) { lastNames.Add("Audrey", "Hepburn"); }
Now here is how it might look after an porting to use the generic type Dictionary<K,V>:
Dictionary<string, string> lastNames; lastNames = new Dictionary<string, string> (); lastNames.Add("Beatrice", "Arthur"); lastNames.Add("Lucille", "Ball"); // the next line throws KeyNotFoundException string name = lastNames["Audrey"]; if (name == null) { lastNames.Add("Audrey", "Hepburn"); }
In Beta 1 the indexer throws an exception if the given key does not exist in the collection. If this is not desirable behavior, you can use the ContainsKey method to check safely if a given key exists. The current behavior makes porting code based on Hashtable to Dictionary<K,V> a bit trickier.
I think the current behavior is justified. What would happen with a Dictionary of integer values when you pass a key that does not exist? There is no possibility of returning null for a value type, and returning a default value (0) seems misleading and bug-prone.
Another gotcha is in the second sentence of the documentation for every generic type:
This class is not CLS-compliant
The question is: Do I care?
I’ve read articles about how being CLS compliant will allow for interoperability with a wider range of .NET languages. This could be important for library designers targeting the 0.4% of the market using Cobol.NET and Fortran.NET. I did a quick test to see the impact on the other 99.1%. First, I put the following in a C# class library:
public class Class1 { public Dictionary<string, int> GetDictionary() { Dictionary<string, int> foo = new Dictionary<string, int>(); foo.Add("test", 2112); return foo; } }
Next, a quick VB program to use the C# class. (I was a little worried I might have to dig to find generics syntax for VB, but my fingers had a spasm and intellisense auto-completed the entire program. It was amazing. Did I mention my cat wrote a Tetris knock-off with Whidbey last week?).
Sub Main() Dim c As New ClassLibrary1.Class1 Dim bar As Dictionary(Of String, Int32) bar = c.GetDictionary() Console.WriteLine(bar("test").ToString()) End Sub
It all just works.
For the applications I work on, generics are powerful enough to sacrifice CLS compliance. I imagine this will be the case for the majority of developers. Porting an existing codebase heavily into collections to the generic types won’t be automatic, but nothing to sweat over if all the unit tests are written, right?
I've been running low on reading material, so I decided it was a good time to go book shopping.
One title that has caught my eye with it's quirkiness is Coding Slave. Judging by the web site, this should be entertaining.
I also found out Neal Peart has a new book on the way. I'm just wondering if I should pre-order through Amazon, or wait until the Rush tour hits Virginia this August. Pehaps some copies might be available for sale there. Decisions, decisions.
First, a new type to work with:
class Person { public Person(string name, DateTime birthday) { this.name = name; this.birthday = birthday; } public string Name { get { return this.name; } set { this.name = value; } } public DateTime Birthday { get { return this.birthday; } set { this.birthday = value; } } string name; DateTime birthday; }
The Comparison<T> delegate represents a method used to compare two types. If you have ever needed to define an entirely new type deriving from IComparer just to tell Array.Sort how to compare two objects, you’ll appreciate the brevity in the following sample.
List<Person> list = new List<Person>(); list.Add(new Person("Alex", DateTime.Now.AddYears(-30))); list.Add(new Person("Neal", DateTime.Now.AddYears(-20))); list.Add(new Person("Geddy", DateTime.Now.AddYears(-25))); list.Sort( delegate(Person x, Person y) { return Comparer<DateTime>.Default.Compare(x.Birthday, y.Birthday); } );
Next is the Converter<T,U> delegate. Use this delegate to convert each object of type T in a collection to type U.
List<int> yearList; yearList = list.ConvertAll<int>( delegate(Person p) { return p.Birthday.Year; } );
Finally, there is the Action<T> delegate. Use this delegate to perform an action with each object of the collection.
yearList.ForEach( delegate(int year) { Console.WriteLine(year); } );
I am generally grouchy about any new language feature until I can write some code and figure out its purpose in life. Generics I knew would be a hit, and after writing this code I’m starting to warm up to anonymous delegates.
If the following code finds a match, we’ll find out it’s a no-no.
foreach (string s in list) { if (s == "two") list.Remove(s); }
In VS2005, the code creates this friendly little dialog.
C# 2.0 introduces generics, and with generics come predicates. A predicate returns true when an object meets a set of conditions, otherwise false. A method like List
list.RemoveAll( delegate(string s) { return s == "Two"; } );
Alternatively, you can keep your logic inside a named method.
static bool MatchTwoPredicate(string s) { if (s == "Two") return true; return false; } // and later . . . list.RemoveAll(MatchTwoPredicate);
I feel either technique is easier on the eyes when compared to STL and functors in C++. Then again, I should be sleeping right now instead of blogging.
While veering through Yahoo news this evening I came across the headline: “FCC Boss Launches Blog Aimed at High-Tech Industry”.
I was stunned.
For the first time ever I read about a new blog from a source outside the blog world. Usually you find out about these sorts of thing by plowing through 25 insightful blog entries which read: “so and so is blogging – subscribed!”.
In true Yahoo / Reuters fashion, however, the news article didn’t contain an actual link to the blog, but links to news and websites about the FCC. At the very bottom of the article, they put in the URL, but not in a hyperlink. I cut and pasted the URL into IE.
I was stunned.
I really thought I had reached the wrong server. I see a big broken banner on the top because ActiveX controls are disabled for the Internet zone. Advertisements and menus appear randomly on the page, and there is a huge gap of whitespace to scroll through before blog entries appear.
[update: i've been informed this is because I also have JavaScript disabled in the Internet zone. DUH! Ah, the pleasures of running Win 2003 Server and hardened security on a desktop machine. Still - the colors give me a headache.]
Then I reached the bottom of the page, which included more advertisements from Sun, IBM, and AOL. On a hunch, I viewed the page in Firefox. Suddenly, the layout improved. Menus aligned. Caverns of white space turned into proper half inch borders.
The colors still give me a headache, but it’s hard to cram 22 advertisements on a page without looking like a dryer full of checkered golf clothes.
Interesting that the head cheese of the FCC has a blog that doesn’t render well in the most popular browser on the planet. [update: ok, maybe it does render with everything enabled, but it's still UGLY!]