DateTimePicker focus issue

The Winforms DateTimePicker has this odd behavior. If you set focus to either the day or the year, then when you tab out of the control and tab back in, focus is not restored to the month as it is by default (even if you reset or change the DateTime value for the control). There is no elegant way to resolve this as the control does not expose those inner controls in any way. You could send mouse/keyboard clicks to change focus, but it’s way simpler to use this arguably ugly hack. The code below will force the control to recreate itself and thus we reset focus to its default state.

var format = dateTimePicker1.Format;
dateTimePicker1.Format = DateTimePickerFormat.Custom;
dateTimePicker1.Format = format;

The trick is to force the control to internally reset itself by changing the Format and then setting it back to what it was. The code above assumes that it is something other than Custom.

Directory.GetFiles and extensions longer than 3 characters

This question pops up in various forums every once in a while. Essentially, someone would call Directory.GetFiles with something like “*.dat” and would be annoyed to find that *.dat matches .dat, .data, and even .date. Not what they wanted.

Unfortunately, this is by design. You have to do post-filtering to select just the files you want.

var files =  Directory.GetFiles(@"d:\tmp", "*.dat").Where(
    s => s.EndsWith(".dat"));

The reason it works this way is most likely for backward compatibility with the old 8.3 file system. And it’s really not a .NET restriction here, it’s an API restriction. Both FindFirstFile and FindNextFile have this behavior and it’s these API calls that are P/Invoked by Directory.GetFiles.

Generic arrays and casting to an object array

This question was posted recently on the CodeProject forums. The OP wanted to know why this code would not compile (I’ve simplified it):

private void FooInternal(object[] values)
{
}

private void Foo<T>(T[] values)
{
    FooInternal(values);
}

The error thrown is:

Error	2	Argument 1: cannot convert from 'T[]' to 'object[]'

The fix is to add a constraint:

private void Foo<T>(T[] values) where T:class
{
    FooInternal(values);
}

If you are wondering why that is needed, consider this code snippet:

struct S
{
}

static void Main(string[] args)
{
    object[] arr = new S[10];
}

That won’t compile either. The reason’s that each of those value type members need to be boxed into an object to get an object array, meaning it’s now a different array. Since that is not standard behavior for casts, the compiler will not automatically do that for you (which is a good thing). If you did it manually, this is what it’d look like:

object[] arr = new S[10].Cast<object>().ToArray();