Saturday, May 31, 2008

IEnumerable vs IEnumerator

IEnumerator<T> generic interface defines "cursor" methods for iterating over a collection:
T Current { get; }
bool MoveNext();
void Reset();
void Dispose();

IEnumerable<T> generic interface defines just one method:
IEnumerator<T> GetEnumerator();

C# supports iterator blocks. These are blocks of code (i.e. method or property getter blocks) in which you "yield" a return value at various points in the code. The compiler uses hidden magic to create a nested type that implements both IEnumerable<T> and IEnumerator<T>; the body of your original method is stubbed out to call into this new object, and all your original logic is implemented in the IEnumerator<T>'s MoveNext method.

The C# foreach keyword is quite flexible and operates on any object that exposes a public GetEnumerator() method (the 'collection' pattern) - the object doesn't have to implement IEnumerable or IEnumerable<T>.

Thursday, May 29, 2008

Experiment in the Fidelity of UTC DateTime

// make sure your local clock is not displaying GMT

DateTime a = new DateTime(2008, 7, 6, 4, 3, 2, DateTimeKind.Utc);
DateTime b = new DateTime(2008, 7, 6, 4, 3, 2, DateTimeKind.Local);
DateTime c = new DateTime(2008, 7, 6, 4, 3, 2, DateTimeKind.Unspecified);

// no surprises here...
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);

// and again, no surprises. this makes it that much more explicit.
Console.WriteLine("-");
Console.WriteLine(a.ToUniversalTime());
Console.WriteLine(b.ToUniversalTime());
Console.WriteLine(c.ToUniversalTime());

// notice the Z(ulu) for UTC, the time zone for local, and the (nothing) for unspecified
Console.WriteLine("-");
XmlSerialize(a);
XmlSerialize(b);
XmlSerialize(c);

// ooh! our first loss of fidelity
Console.WriteLine("-");
DataSet dataSet = new DataSet();
DataTable dataTable = dataSet.Tables.Add();
DataColumn dataColumn = dataTable.Columns.Add("DateTime", typeof(DateTime));
dataTable.Rows.Add(a);
dataTable.Rows.Add(b);
dataTable.Rows.Add(c);
Console.WriteLine(dataSet.GetXml());

// those .net framework guys fight back with the DateTimeMode property (new in 2.0)
// understandably, weird stuff starts happening when not all input dates are of the same kind
Console.WriteLine("-");
DataSet dataSet2 = new DataSet();
DataTable dataTable2 = dataSet2.Tables.Add();
DataColumn dataColumn2 = dataTable2.Columns.Add("DateTime", typeof(DateTime));
dataColumn2.DateTimeMode = DataSetDateTime.Utc;
dataTable2.Rows.Add(a);
dataTable2.Rows.Add(b);
dataTable2.Rows.Add(c);
Console.WriteLine(dataSet2.GetXml());

//you can't just get the bytes for a DateTime, it's a struct.
//Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(a)));
//Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(b)));
//Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(c)));

Console.ReadKey();

Tuesday, May 27, 2008

Flex interaction with JavaScript (and ASP.NET)

It just doesn't quite work out of the box.

First, a flash object within an HTML form element fails when the flash runtime tries to register the callbacks you defined in your Flex app (e.g. a callback added in ActionScript using ExternalInterface.addCallback("someFunction", someFunctionPointer) is evaluated in the browser as __flash__addCallback(objectId, "someFunction"). A hack to get around this would be to assign your Flash object to window.objectId as soon as you've created it: hey presto! you've worked around one limitation.

Second. There appears to be a race condition if you need to initialize your Flex app with JavaScript data as soon as both are ready. At first, I thought I had a choice... push from JavaScript or pull from Flex. To push, we need to know that the callback has been added in the browser: either by polling or by registering an event. I refuse to poll, and I can't find a way to register for the event. The remaining option is to pull. The question is, will the source data (JavaScript) have been assigned by the time my Flex Application's applicationComplete event has fired? No idea, really.