April 2004 - Posts

Brad wanted to know whether or not we minded the exception if the key value didn't exist on his original post on the matter The change from Hashtable to Dictionary .  I figured the reason people would use the exception would be for using integral value types in their dictionaries.  The workaround is to use a Nullable type over the top of the integral type, and then you can always have the ability to return a null value.  You'd think the integral type dictionary would be slightly faster (it will at least take slightly less memory), and that Nullable would be a little slower.  I've found that for some reasons Nullable is actually a little bit faster.  Not sure why, but it is about 50% faster over a simple loop.  Maybe it will be smart to use Nullable types instead of integral types (full source at the end).

Some people on the original thread also said that a Try* method would be sufficient.  Well, there is a Try* method.  It is called TryGetValue and returns a bool for found versus not and an out parameter of the type of your value parameter.  Here is a short sample usage of the function, with a full sample at the end.

string[] keysToTest = new string[] { (keyBase + 50).ToString(), (keyBase + keys + 1).ToString() };
foreach(string key in keysToTest) {
    int intValue = 0;
    if ( intDictionary.TryGetValue(key, out intValue) ) {
        Console.WriteLine("Found: {0}", intValue);
    } else {
        Console.WriteLine("Not Found: {0}", key);
    }
}

I think they've done their job already.  Why change the exception logic, when you already have to do extra work to create the generic dictionary, you might as well do a bit of work to switch over to using the TryGetValue method.  One problem is that it isn't obvious (no code breaks) that you are using the indexer and so you might forget to change a piece of legacy code to use TryGetValue where needed.  My original comments are on this matter are here Darnit, they break the Hashtable (err Dictionary) then ask us how we think they should fix it...

using System;
using System.Collections.Generic;

public class NullableVsValueType {
    const int keyBase = 10000000;
    const int keys = 1000000;
   
    private static void Main(string[] args) {
        string[] stringsForKeys = new string[keys];
        int counter = 0;
        Dictionary<string, int> intDictionary = new Dictionary<string, int>();
        Dictionary<string, Nullable<int>> nullableDictionary = new Dictionary<string, Nullable<int>>();

        DateTime start, end;
       
        Console.WriteLine("Start Pre-Processing Strings");
        start = DateTime.Now;
        for(int i = keyBase; i < (keyBase + keys); i++) {
            stringsForKeys[i - keyBase] = i.ToString();
        }
        end = DateTime.Now;
        Console.WriteLine("Pre-Processing Strings Complete: {0}", end - start);
        Console.WriteLine();
       
        Console.WriteLine("Start Int Dictionary");
        start = DateTime.Now; counter = 0;
        for(int i = 0; i < keys; i++) {
            intDictionary[stringsForKeys[i]] = i;
            // counter += intDictionary[stringsForKeys[i]];
        }
        end = DateTime.Now;
        Console.WriteLine("Int Dictionary Complete: {0}, {1}", end - start, counter);
        Console.WriteLine();
       
        Console.WriteLine("Start Nullable<Int> Dictionary");
        start = DateTime.Now; counter = 0;
        for(int i = 0; i < keys; i++) {
            nullableDictionary[stringsForKeys[i]] = i;
            // nullableDictionary[stringsForKeys[i]] = new Nullable<int>(i);
            // counter += nullableDictionary[stringsForKeys[i]].Value;
        }
        end = DateTime.Now;
        Console.WriteLine("Nullable<Int> Dictionary Complete: {0}, {1}", end - start, counter);
        Console.WriteLine();
       
        Console.WriteLine("Using TryGetValue");
        string[] keysToTest = new string[] { (keyBase + 50).ToString(), (keyBase + keys + 1).ToString() };
        foreach(string key in keysToTest) {
            int intValue = 0;
            if ( intDictionary.TryGetValue(key, out intValue) ) {
                Console.WriteLine("Found: {0}", intValue);
            } else {
                Console.WriteLine("Not Found: {0}", key);
            }
        }
    }
}

[Edit: Adding more complete test code for timing both string keying as above, and integer keying.  One user's comments point that the keying is causing changes on his machine that make the integral value dictionary perform better than the Nullable type dictionary.  I can't repro his case, so I'm attempting to standardize the test case so there aren't any discrepancies.  You can get the latest test code here Nullable Versus Integral Data Types (C# 2.0 Test Code)]

Posted by Justin Rogers | 6 comment(s)
Filed under:

I figured it would take me a few hours to pump out a decent ForEach sample, but I'm not thinking so.  At first I figured ForEach would provide a bunch of enumerator protection semantics, but it doesn't.  It just does a for loop over the internal array (and not because of the C# foreach optimization either, since this guy only has a single local int and they aren't making a copied reference of the _items array). 

Well hell, I can do that.  I've added the ForEach that now takes a list to mutate, a sub list predicate, a sub list converter (as in the last article), but adds the concept of a BreakAction.  Why a BreakAction?  Well, because the System.Action<T> delegate doesn't support a boolean return value.  How do you break out of a foreach statement?  Well, you use a break; call.  You can't do that with the System.Action<T> delgate, so I created a BreakAction<T> delegate that will work.  Note that BreakAction<T> now also uses SubType whereas the ForEach on the List<T> would make use of ListType.

Since delegates make heavy use of type parameters when declaring EVERYTHING, it wouldn't save you much code to put these helper methods on the List<T> now that I think about it.  ForEach by default could do what it does now, but as soon as you start adding the sub-list parsing, the calling code would look just as ugly as the runnable code sample here:

using System;
using System.Collections;
using System.Collections.Generic;

public class Organism {}
public class Plant : Organism {}
public class Animal : Organism {}
public class Carnivore : Animal {}
public class Herbivore : Animal {}
public interface ISeaPlant {}
public interface ILandPlant {}
public class SeaPlant : Plant, ISeaPlant {}
public class LandPlant : Plant, ILandPlant {}

public delegate bool BreakAction<DataType>(DataType dataToProcess);
public class GenericForEachEnhancement {

    private static void Main(string[] args) {
        List<Organism> organisms = new List<Organism>(30);
        for(int i = 0; i < 10; i++) {
            organisms.Add(new Plant());
            organisms.Add(new SeaPlant());
            organisms.Add(new LandPlant());
            organisms.Add(new Carnivore());
            organisms.Add(new Herbivore());
        }
       
        bool enumerationBreak = ForEach<Plant, Organism>(
            organisms,
            new Predicate<Organism>(PlantsOnlyPredicate),
            new Converter<Organism, Plant>(PlantsConverter),
            new BreakAction<Plant>(MyBreakAction));
           
        Console.WriteLine();
        Console.WriteLine("Enumeration Break?: {0}", enumerationBreak);
    }
   
    private static bool PlantsOnlyPredicate(Organism underlying) {
        if ( underlying is Plant ) { return true; } else { return false; }
    }

    private static Plant PlantsConverter(Organism input) {
        return input as Plant;
    }
   
    private static Random rand = new Random();
    private static bool MyBreakAction(Plant plantToProcess) {
        Console.WriteLine("Processing Plant");
       
        return (rand.Next(0, 30) == 0);
    }
   
    private static bool ForEach<SubType, ListType>(
        List<ListType> listToMutate,
        Predicate<ListType> subListPredicate,
        Converter<ListType, SubType> subListConverter,
        BreakAction<SubType> actionOrBreak) {
       
        // I would be using FindAllMutate probably, but I'll just rewrite the code here
        foreach(ListType listItem in listToMutate) {
            if ( subListPredicate(listItem) ) {
                if ( actionOrBreak(subListConverter(listItem)) ) {
                    return true;  // The enumeration was broken
                }
            }
        }
       
        // The enumeration full completed
        return false;
    }
}

The last step in the process (making this work for ControlCollection) will definitely have to come later.  Time for bed.

Posted by Justin Rogers | 1 comment(s)
Filed under:

By a raise of hands, how many people love foreach?  I'm starting to like it quite a bit, even though I often refactor it out of a loop because I need the index.  That is probably the number one reason people actually perform the refactoring.  However, when using any non enumeration syntax, you don't get the versioning concepts that are available to enumerators, and so if the collection changes you never know.  This could be a big deal, or it might not, but the versioning is pretty neat nonetheless.

Being as I loved foreach, I figured they'd give it some love in Whidbey.  I'm back to looking at List<T>.  So if I grab an enumerator off of List<T> I can't pass it a Predicate<T>.  Have you see predicates yet?  They allow you to return a true/false as to whether or not something matches your criterion.  So enumeration in a collection can't have predicates.  Well, that kind of sucks, and is something I'd love to see added at the base level.  Basically:

GetEnumerator(new Predicate<TypeICreatedCollectionWith>(MyPredicate));

Sweet.  Now I can enumerat only those items that match my list, skipping over any that don't.  That would be perfect, but it doesn't exist yet.  So what does exist?  Well, FindAll.  This returns a List<T> based on your closed type.  Keyword is that it creates a new collection.  Not the best, but you can do it.  I'll include a full sample as the end, but a FindAll call might look like the following:

List<Organism> organisms = new List<Organism>(30);
for(int i = 0; i < 10; i++) {
    organisms.Add(new Plant());
    organisms.Add(new SeaPlant());
    organisms.Add(new LandPlant());
    organisms.Add(new Carnivore());
    organisms.Add(new Herbivore());
}

List<Organism> plants = organisms.FindAll(new Predicate<Organism>(PlantsOnlyPredicate));

The above PlantsOnlyPredicate obviously checks the type and does some work.  Notice the problem with the above?  My Predicate only returns Plants, however, List<T> is of open type Organism still.  Even worse, you can't just cast it around like you used to be able to.  So FindAll doesn't support mutation.  Is there a method that does?  Yep.  ConvertAll.  ConvertAll takes a Converter<T,V> and returns you a new List<V>.  So now the code looks something like:

List<Organism> plants = organisms.FindAll(new Predicate<Organism>(PlantsOnlyPredicate));
List<Plant> castPlants = plants.ConvertAll(new Converter<Organism, Plant>(PlantConverter));

I think it is time these two got merged eh?  What about taking a FindAll, that ALSO took a converter.  You could write a method that returned the new strongly typed collection cast up if need be.  That seems pretty cool right?  Well, it could cast an exception if your converter can't make the cast, but that really is the programmers problem.  To get back to the original problem, you now have to FindAll, ConvertAll, and then GetEnumerator to get an enumerator for only a specific sub-set of your collection (you can take out the ConvertAll if your predicate isn't doing work based on type, but instead based on some other criterion, but I remember users that wanted to enumerate over say a collection of controls, but only enumerate the buttons, say in a WinForms environment).

I have two solutions really.  The first solution just does the conversion.  It has to box the value (cast to object) in order to get around the compiler junk, but it does return your strongly typed array cast to whatever the ReturnType is.  Check it out, but notice the casting doesn't look cool because we aren't using the indirection of a converter:

private static List<ReturnType> FindAllMutate<ReturnType, ListType>
    (List<ListType> listToMutate, Predicate<ListType> predicate)
{
    List<ReturnType> mutator = new List<ReturnType>();

    foreach(ListType listItem in listToMutate) {
        if ( predicate(listItem) ) {
            mutator.Add((ReturnType) ((object) listItem));
        }
    }

    return mutator;
}

Note, you can't really use constraints here.  Why?  Well, because think of how they work and get back to me if you find a way to use them.  I couldn't find a way to do the conversion generically with a constraint since the conversion could be to a class derived from ListType, a class ListType is deriving from, or an interface ListType is implementing.

I think the Converter is pretty nice though.  It basically forces you to write a method with the ListType as a parameter and an output of the ReturnType.  C# will then worry about your casting later and as long as your Converter is written for the type you are converting, then the methods all work.  Very nice, since now the compiler has more information.  Rewritten with the converter the FindAllMutate now looks different.

private static List<ReturnType> FindAllMutate<ReturnType, ListType>
    (List<ListType> listToMutate, Predicate<ListType> predicate, Converter<ListType, ReturnType> converter)
{
    List<ReturnType> mutator = new List<ReturnType>();

    foreach(ListType listItem in listToMutate) {
        if ( predicate(listItem) ) {
            mutator.Add(converter(listItem));
        }
    }

    return mutator;
}

Well, no more sloppying casting.  And I can write whatever I would like in my converter, including custom code that knows how to create the proper type even if there isn't an easy conversion. 

That appears to accomplish my goals for this blog.  I'd love to see some more powerful collection routines added to List at the base rather than writing them.  That way I can be assured they'll be there as I'm writing code for customers.  I'm not seeing any real generics support in the Windows Forms library, so my original problem of enumerating the Controls collection for only the controls matching a particular type might not be as close as I think.  Here is some test code for predicates with a Terrarium theme, Enjoy!

using System;
using System.Collections;
using System.Collections.Generic;

public class Organism {}
public class Plant : Organism {}
public class Animal : Organism {}
public class Carnivore : Animal {}
public class Herbivore : Animal {}
public interface ISeaPlant {}
public interface ILandPlant {}
public class SeaPlant : Plant, ISeaPlant {}
public class LandPlant : Plant, ILandPlant {}

public class PredicateCategorizer {
    private static void Main(string[] args) {
        List<Organism> organisms = new List<Organism>(30);
        for(int i = 0; i < 10; i++) {
            organisms.Add(new Plant());
            organisms.Add(new SeaPlant());
            organisms.Add(new LandPlant());
            organisms.Add(new Carnivore());
            organisms.Add(new Herbivore());
        }

        List<Organism> plants = organisms.FindAll(new Predicate<Organism>(PlantsOnlyPredicate));
        Console.WriteLine(plants.Count);
        List<Organism> herbivores = organisms.FindAll(new Predicate<Organism>(HerbivoresOnlyPredicate));
        Console.WriteLine(herbivores.Count);
        List<Organism> carnivores = organisms.FindAll(new Predicate<Organism>(CarnivoresOnlyPredicate));
        Console.WriteLine(carnivores.Count);
       
        List<Plant> plantsPreCast = FindAllMutate<Plant, Organism>(organisms, new Predicate<Organism>(PlantsOnlyPredicate));
        Console.WriteLine(plantsPreCast.Count);
       
        List<ISeaPlant> plantsSeaOnly = FindAllMutate<ISeaPlant, Organism>(organisms, new Predicate<Organism>(SeaPlantsOnlyPredicate), new Converter<Organism, ISeaPlant>(SeaPlantConverter));
        Console.WriteLine(plantsSeaOnly.Count);
    }
   
    private static Plant PlantsConverter(Organism input) {
        return input as Plant;
    }

    private static ISeaPlant SeaPlantConverter(Organism input) {
        return input as ISeaPlant;
    }
   
    private static bool PlantsOnlyPredicate(Organism underlying) {
        if ( underlying is Plant ) { return true; } else { return false; }
    }

    private static bool SeaPlantsOnlyPredicate(Organism underlying) {
        if ( underlying is ISeaPlant ) { return true; } else { return false; }
    }

    private static bool HerbivoresOnlyPredicate(Organism underlying) {
        if ( underlying is Herbivore ) { return true; } else { return false; }
    }

    private static bool CarnivoresOnlyPredicate(Organism underlying) {
        if ( underlying is Carnivore ) { return true; } else { return false; }
    }
   
    private static List<ReturnType> FindAllMutate<ReturnType, ListType>
        (List<ListType> listToMutate, Predicate<ListType> predicate, Converter<ListType, ReturnType> converter)
    {
        List<ReturnType> mutator = new List<ReturnType>();

        foreach(ListType listItem in listToMutate) {
            if ( predicate(listItem) ) {
                mutator.Add(converter(listItem));
            }
        }

        return mutator;
    }

    private static List<ReturnType> FindAllMutate<ReturnType, ListType>
        (List<ListType> listToMutate, Predicate<ListType> predicate)
    {
        List<ReturnType> mutator = new List<ReturnType>();

        foreach(ListType listItem in listToMutate) {
            if ( predicate(listItem) ) {
                mutator.Add((ReturnType) ((object) listItem));
            }
        }

        return mutator;
    }
}

Posted by Justin Rogers | 9 comment(s)
Filed under:

The new Console in Whidbey really is fun.  I have some small complains, but I'm guessing I could write enough code to get around them.  My biggest complaint is that you aren't given good enough integration with WriteConsoleOutput(...).  In fact they don't even use WriteConsoleOutput, but instead use WriteFile on the output handle.  They probably do this because of output redirection and the what not and the reliance that everything works with a TextWriter.  WriteConsoleOutput will only write to a console handle and if you give it a non console handle it fails.

What do you get from WriteConsoleOutput?  A lot.  You get the opportunity to specify attributes per character, enabling you to most efficiently write colored text to the screen.  Otherwise you have to do a lot of Foreground/Background color sets.  Since we can't get access to WriteConsoleOutput (well, we could, but we won't since that would defeat the purpose of half the new console stuff), we'll instead go for something a bit different.  Namely, limited ANSI terminal code support. 

How does ANSI terminal coding work?  Well, you specify an escape sequence of the form “\e[” or in C# “\x1B[” since \e isn't a character escape by default.  We'll only be supporting colors for now, so the key sequence accepted is of the form “\e[#,(optional #, optional #, ...)mThe Text To Color”.  You can specify as many codes or numbers as you want.  I'll also implement ConsoleColor names in place of numbers.  However, since ConsoleColor doesn't differentiate between background and foreground colors, the first color (if not a number) will be the foreground and the second the background.  That is simply how it works.  You can also specify the \e[0m flags which specify that the default colors should be used.  These are normally defined as white on black I think, but I've taken them to mean the colors that were set when the program was started or at least the colors that were set the first time you called WriteColoredLine (aka, there is no global handling, though we could have used ResetColor to force the console to grab the defaults).  Anyway, attached is a small sample program.  I'm thinking about adding some additional support for other flags, namely bold, dark, concealed, and reverse.  I also think Blink would be fairly easy, but some enhancements would have to be made to add an animation controller and synchronized writing.  You would never be able to write to Console.WriteLine and would instead need to use some helper class for all output (Terminal.WriteLine?) so that while the buffer was being updated with animations you couldn't write to the screen.  As soon as the animation frame was done your text would go to the terminal.  Anway, I'm having too much fun with this, so I”ll leave you to your own designs.

using System;
using System.Text.RegularExpressions;

public class ConsoleQuickColor {
    private static void WriteColoredLine(string writeColored) {
        WriteColored(writeColored + "\n");
    }
   
    private static void WriteColored(string writeColored) {
        ConsoleColor foreColor = Console.ForegroundColor;
        ConsoleColor backColor = Console.BackgroundColor;
       
        if ( !writeColored.StartsWith("\x1B") ) {
            writeColored = "\x1B[0m" + writeColored;
        }
       
        MatchCollection matches = Regex.Matches(writeColored, "\\e\\[(?<colorCodes>.+?)m(?<textToWrite>.+?)(?=(\\e\\[|\\z))", RegexOptions.Singleline | RegexOptions.Multiline);

        Nullable<ConsoleColor> currentFore = null;
        Nullable<ConsoleColor> currentBack = null;
        foreach(Match m in matches) {
            string[] codesToProcess = m.Groups["colorCodes"].Value.Split(';');
            string textToWrite = m.Groups["textToWrite"].Value;
           
            for(int i = 0; i < codesToProcess.Length; i++) {
                switch(codesToProcess[i]) {
                    case "Reset":
                    case "Clear":
                    case "0":
                        currentFore = null;
                        currentBack = null;
                        break;
                    case "30":
                        currentFore = ConsoleColor.Black;
                        break;
                    case "31":
                        currentFore = ConsoleColor.Red;
                        break;
                    case "32":
                        currentFore = ConsoleColor.Green;
                        break;
                    case "33":
                        currentFore = ConsoleColor.Yellow;
                        break;
                    case "34":
                        currentFore = ConsoleColor.Blue;
                        break;
                    case "35":
                        currentFore = ConsoleColor.Magenta;
                        break;
                    case "36":
                        currentFore = ConsoleColor.Cyan;
                        break;
                    case "37":
                        currentFore = ConsoleColor.White;
                        break;
                    case "40":
                        currentBack = ConsoleColor.Black;
                        break;
                    case "41":
                        currentBack = ConsoleColor.Red;
                        break;
                    case "42":
                        currentBack = ConsoleColor.Green;
                        break;
                    case "43":
                        currentBack = ConsoleColor.Yellow;
                        break;
                    case "44":
                        currentBack = ConsoleColor.Blue;
                        break;
                    case "45":
                        currentBack = ConsoleColor.Magenta;
                        break;
                    case "46":
                        currentBack = ConsoleColor.Cyan;
                        break;
                    case "47":
                        currentBack = ConsoleColor.White;
                        break;
                    default:
                        int numericValue = 0;
                        if ( !int.TryParse(codesToProcess[i], out numericValue) ) {
                            if ( i == 0 ) {
                                try {
                                    currentFore = (ConsoleColor) Enum.Parse(typeof(ConsoleColor), codesToProcess[i], true);
                                } catch {}
                            } else if ( i == 1 ) {
                                try {
                                    currentBack = (ConsoleColor) Enum.Parse(typeof(ConsoleColor), codesToProcess[i], true);
                                } catch {}
                            }
                        }
                        break;
                }
            }
           
            Console.ForegroundColor = (currentFore.HasValue) ? currentFore.Value : foreColor;
            Console.BackgroundColor = (currentBack.HasValue) ? currentBack.Value : backColor;
            Console.Write(textToWrite);
        }
       
        Console.ForegroundColor = foreColor;
        Console.BackgroundColor = backColor;
    }
   
    private static void Main(string[] args) {
        for(int i = 0; i < 16; i++) {
            for(int j = 0; j < 16; j++) {
                WriteColored("\x1B[" + ((ConsoleColor) i).ToString() + ";" + ((ConsoleColor) j).ToString() + "m Hi! ");
            }
            Console.WriteLine();
        }
   
        WriteColoredLine("\n\n\x1B[Blue;BlackmBlue on Black");
        WriteColoredLine("This should use the default text");
        WriteColoredLine("\x1B[40;40;40;37;34;45mA really stupid sequence.  We'll take the last\n");
    }
}

Posted by Justin Rogers | with no comments
Filed under:

Collections, are collection, are collections.  NOT!  Collections are arrays somewhere, at least in most cases.  More often than not I find myself using an ArrayList (in V1/1.1) and then converting the said list to a strongly typed array for quickly running over the values.  The conversion is fine for smaller arrays, but for larger arrays the conversion really sucks, and it takes up twice the memory.  After all, don't you already have a collection back there somewhere?

Well, for ArrayList it makes sense they made us do all the copying since the backing array was of type System.Object.  But now we have List<T>.  The array backing that is already strongly typed and ready to go.  Hell, shouldn't I be able to get a reference directly to the already built array for use?  Sure it may have a couple of extra elements that I don't need, but it is up to me to handle the esoterics of indexing.  What is currently available and what am I looking for?

There is already a CopyTo method that I could use.  However, this is exactly what it says, a copy.  There is also a ToArray, but that creates a copy of the array.  You could say I should just use the indexer on List<T> since it is now strongly typed, however, get_Item() has a bunch of crappy range checking logic that is going to slow me down just that little bit.  What I'm looking for is a Decompose method.  Reset the internal state of the collection to a new array, and return me the reference to the old array.  Of course your ReadOnlyList would throw an exception on this, as it should, but your normal List<T> should run just fine.  After all, the user could always just call Clear, so it isn't like the internal array you are using is sacrosant in any way to warrant the protection of it.

Any takers?  Anyone think that direct access to the underlying array without copying for things like Stack<T>, Queue<T>, and List<T> would help out any?

Don't mind the title, I'm just being funny.  However, throwing exceptions isn't a funny matter, so go comment on Brad's post as to how you think they should fix the Dictionary issues with exceptions.  The change from Hashtable to Dictionary

I have the following comments that I'd like to introduce.  First off, Nullable<T> is definitely the way to implement null return values for value types.  It is just super great.  What I don't like about Nullable<T> is that there is no way to easily find out if the underlying type parameter for your ValueCollection is actually of some Nullable<T>.  In other words, is works on closed types, not open types, so you have to do a bunch of voodoo (namely GetGenericTypeDefinition), just to check and see if the type parameter for your ValueCollection is Nullable.  Likewise, you'd have to do similar work to find out if it was an object.  Might make sense to toss an INullable on Nullable so you can quickly check using an is comparison and provide interface based access to HasValue.  Am I wrong here?  Am I missing a language feature that would make checking against the open generic type easy?

So the new Dictionary now follows the following: a) If reference type return null, If Nullable<T> then return Nullable<T>.default, If a ValueType that isn't Nullable<T> then throw that weird exception.

My only argument for not just moving to the ContainsKey() model would be the extra calls.  Also, you still support the default indexed setter which can either Add a value or update it depending.  Not having the null return getter just doesn't make sense.

booleanSettings[“NonExistentKey1“] = foo; // This adds the key if it doesn't exist
foo = booleanSettings[”NonExistentKey2”]; // But this throws an exception...

So I'm definitely thinking things have to be done the right way here (using some nullable feature set).  And that the work involved in implementing that within the Dictionary is actually not going to be clean and easy because C# doesn't have a language feature for getting type information on open generic types nor comparing types against open generic types (hint, hint, maybe something could be added to help?).  Adding the INullable interface would be a total hack and I don't even know why I suggested it.  If you are curious about the open type comparision stuff I'm talking about, check the following code required to compare the types Nullable<string> and Nullable<bool>.  The purpose of the comparison is to determine if the underlying type is actually any instance of Nullable irregardless of the type parameters used in the closed types.

// The below is extremely ugly.
Console.WriteLine(typeof(Nullable<string>).GetGenericTypeDefinition() == typeof(Nullable<bool>).GetGenericTypeDefinition());

// This is how it would look if you actually wanted to see if the underlying type parameter used to create
// your ValueCollection/Dictionary.  Note this must be used in the dictionary class
(this.GetType().GetGenericArguments[1].GetGenericTypeDefinition() == typeof(Nullable<int>).GetGenericTypeDefinition());

I sure hope I'm missing a language feature, because that stuff is UGLY.

Posted by Justin Rogers | 6 comment(s)
Filed under: ,

I love the console window, especially under NT.  Now, most people don't understand why, because they've never used the console to it's full potential.  They think the console is all about basic textual output in a linear in/linear out fashion.  But it is so much more.  Here is just a small smattering of the features on an NT console (and also on the new Whidbey System.Console):

  • Coloring support.  You can now set the Foreground and Background colors when rendering text.  You get your choice of among 16 different colors for a total of 256 different combinations.
  • Access to a bunch of special characters including Ctrl+C, Ctrl+Break, Caps Lock, Num Lock, and if you check the ConsoleKey enumeration you can get access to the voume up/down buttons present on some modern day keyboards.  Very cool stuff.
  • You can set the location and size of the window now and the title (very important my friend).  You can also set the size of the available screen buffer in case you wanted to push out a lot of text and then let the user scroll about to see it all.
  • My favorite feature is cancelling the break event.  This allows you to keep the console open during long running operations without losing full control.  The user can issue Ctrl+C and you can trap that event to give them an option of gracefully exiting the LRO.
  • You can also set the cursors position.  This is where output will occur.  Remember those progress notification routines that would update the progress in place?  Well those are now fully and easily possible.

Why would I even talk about this new console rather than just writing my own that works on V1.1?  After all that is my normal agenda.  But not today.  I think they've done so well with the Whidbey console that I'll just wait.  In the meantime I'll throw out samples using the Whidbey stuff so you can see how cool the console really is.  Here is a small progress notification sample that supports asking the user if they want to cancel.  The operation continues while the user is being polled, so it might just finish before they say yes or no.

using System;
using System.Threading;

public class ConsoleCancel {
    private static bool cancel = false;
    private static int progress = 0;
    private static int initialTop;

    private static void Main(string[] args) {
        Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
       
        initialTop = Console.CursorTop;
        while(!cancel) {
            progress++;
            if (progress >= 100 ) {
                cancel = true;
            }
            Console.CursorTop = initialTop;
            Console.CursorLeft = 0;
           
            Console.WriteLine("{0,3}% Complete", progress);
            Thread.Sleep(100);
        }

        Console.CursorTop = initialTop + 4;
    }
   
    private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e) {
        e.Cancel = true;
       
        Console.CursorTop = initialTop + 2;
        Console.CursorLeft = 0;
        Console.WriteLine("Would you like to cancel the LRO?");
        ConsoleKeyInfo returnKey = Console.ReadKey(true);

        if ( returnKey.Key == ConsoleKey.Y ) {
            cancel = true;
        } else {
            Console.CursorTop = initialTop + 2;
            Console.CursorLeft = 0;
            Console.Write(new string(' ', Console.BufferWidth));
            cancel = false;
        }
    }
}

I'm kind of bummed that you have to save the initialTop variable so you can use it for positioning.  Seems like something they'd save on the class itself.  I'm also kind of bummed there isn't a clear method to quickly and easily clear a region.  However, I can say I've found a way around this using MoveBufferArea.  I'll talk about some of this stuff later, since I want to do some cool console apps now.

Posted by Justin Rogers | 1 comment(s)
Filed under:

I guess blogger or whatever the heck he was using over in Curious about the lives of up and coming game developers and their schooling? simply wasn't good enough for this up and coming game programming student.  He has since moved over to dotnetjunkies, since they were nice enough to give him a blog spot.  I'm guessing now he has built in RSS and all of those other features you would expect that you can't get out of the free blogger account.  Anyways, if you have him on your aggregator, update your links since he is moving to http://dotnetjunkies.com/WebLog/jwinkle/

Posted by Justin Rogers | with no comments
Filed under: ,

Note this is a completely unfair test because Whidbey is in Beta and all, but I'll throw it out there anyway.  I went ahead and tested the original TryParseInt method (the completely unoptimized version that has been deprecated in the utility), against TryParseInt32 (the fully optimized version), and int.TryParse.  Note that all of the conversions were valid conversions, and full validity checking was in place for all three methods (aka, make sure the value that goes in is the value coming back out).  Fortunately, TryParse is only 7x slower than TryParseInt32 now, which is a step in the right direction, and it doesn't throw exceptions, nor require a cast from double in the case you used double.TryParse.  I'm definitely glad they added the new TryParse methods because they give you one liner options that you would have needed a bit of code for before.

C:\Projects\CSharp\Performance\NumberUtilities>TryParseInt32
Preallocate strings
Preallocation complete
TryParseInt: 00:00:01.0114544
TryParseInt32: 00:00:00.3404896
int.TryParse: 00:00:02.5336432

// Old options without DWC.NumberUtilities or the new BCL TryParse methods
// The old try method
try { int.Parse(); } catch {} 

// The double TryParse method with range checking
double.TryParse(); if (retVal < int.MinValue || retVal > int.MaxValue) {}

Users of the Terrarium client application are going to love the latest changes.  Lots of extra eye candy (go check out Mitch Walker's blog for some screenies), a bunch of code fixes, AND the full source code.  However, I think the server guys are getting left behind.  What have we added to the server for people to look forward to?

  • A VS .NET Project is now present for building the web application.  Unfortunately this means we moved all of the code to code-behind files and it is a bit harder to look at.  I never could understand why someone would use code-behind for web services.
  • We got rid of the OWC dependency!  Yay!  This was a big win.  We actually pushed out a small version of the server internally that used a custom charting component, so the OWC dependency was removed, but that never got released externally.  With the latest release, there aren't any dependencies on external components any more, so you don't have to worry about finding an old copy of Office.
  • Some small UI clean-ups have gone into the application.  In general, it is still a bare-bones server, so don't expect much.  Most of the feature set was placed into making the installation easy and seamless.
  • Seamless install process.  Well, almost seamless.  There is no such thing as a seamless install process because there are too many stupid little dependencies to check for.  The latest install process should let you exit the installer and immediately start using the server.  Just in case the installer isn't good enough, we've included a server setup helper application that blasts the server into place.  All of the old dependency files are now embedded as resources as well, so no accidentally deleting required files.  Gotta love that.

I've been holding off the release of the Terrarium Server : Community Edition until after the MS source release.  The TS:CE will have lots of additional enhancements that will improve the server experience even more.  Namely a fully refactored database, enhanced reporting and statistics roll-ups, and several new service methods for enhanced client features that I'll also detail once the source release hits the web.  I hate having so many dependencies on the public release of the source, but that is the way the cookie crumbles.

More Posts Next page »