Tuesday, March 28, 2006
C# makes a struct invalid by default
C# creates invalid structures when there are array members, as illustrated in the following example:
class Program
{
public struct Problems
{
public int[] iArray;
}
static void Main(string[] args)
{
Problems oProblems = new Problems();
Console.WriteLine("Length = {0}",
oProblems.iArray.Length);
}
}
This example will build but fail when run. The default constructor for Problems does not initialize iArray. It is impossible to remedy the situation by writing a default constructor, because C# insists on providing the default constructor of a struct automatically.
A workaround is to provide any struct that contains an array with an initializing method, as in the following:
class Program
{
public struct Problems
{
public int[] iArray;
public void Initialize()
{
iArray = new int[0];
}
}
static void Main(string[] args)
{
Problems oProblems = new Problems();
oProblems.Initialize();
Console.WriteLine("Length = {0}",
oProblems.iArray.Length);
}
}
Neither Microsoft's opaque C# documentation nor Herb Schildt's generally useful book, "C# 2.0 The Complete Reference," describe this problem or explain that a struct may include methods. The workaround is not really satisfactory, because programmers must remember to invoke initializing methods or otherwise initialize array members of a struct.
class Program
{
public struct Problems
{
public int[] iArray;
}
static void Main(string[] args)
{
Problems oProblems = new Problems();
Console.WriteLine("Length = {0}",
oProblems.iArray.Length);
}
}
This example will build but fail when run. The default constructor for Problems does not initialize iArray. It is impossible to remedy the situation by writing a default constructor, because C# insists on providing the default constructor of a struct automatically.
A workaround is to provide any struct that contains an array with an initializing method, as in the following:
class Program
{
public struct Problems
{
public int[] iArray;
public void Initialize()
{
iArray = new int[0];
}
}
static void Main(string[] args)
{
Problems oProblems = new Problems();
oProblems.Initialize();
Console.WriteLine("Length = {0}",
oProblems.iArray.Length);
}
}
Neither Microsoft's opaque C# documentation nor Herb Schildt's generally useful book, "C# 2.0 The Complete Reference," describe this problem or explain that a struct may include methods. The workaround is not really satisfactory, because programmers must remember to invoke initializing methods or otherwise initialize array members of a struct.
Monday, March 20, 2006
Proximity and "fuzzy" searching
As of 2006, the ASP.NET framework does not support proximity or fuzzy search, although Microsoft does provide these capabilities in SQL Server and Office automation. For data that can be characterized phonetically, Adam Nelson has released a codeset, available at http://www.codeproject.com/csharp/dmetaphone5.asp, implementing the Double Metaphone algorithm developed by Lawrence Phillips. This algorithm is most effective for English.
Wednesday, March 08, 2006
Reset? Reset!
Herb Schildt's book "C# 2.0 The Complete Reference" claims that C# enumerators have a Reset() method that restores the inital state created by a GetEnumerator() method on an enumerable object (pp. 737 and 765).
Great idea, Herb! Do tell Microsoft about it, too, won't you? When you try this method for enumerators over generic collections, you will be surprised. It's not there.
Most enumerators, like those for arrays, have a Reset() method. However, for generic collections Microsoft chose not to implement the usual IEnumerator interface, instead implementing the "IEnumerator Generic" interface, which lacks a Reset() method. ASP.NET 2.0 documentation is otherwise opaque. The Reset() method does not depend on data types of a collection and could easily have been implemented.
The workaround is to execute the required GetEnumerator method again. That will require making the source object accessible when otherwise it would not have been needed.
Great idea, Herb! Do tell Microsoft about it, too, won't you? When you try this method for enumerators over generic collections, you will be surprised. It's not there.
Most enumerators, like those for arrays, have a Reset() method. However, for generic collections Microsoft chose not to implement the usual IEnumerator interface, instead implementing the "IEnumerator Generic" interface, which lacks a Reset() method. ASP.NET 2.0 documentation is otherwise opaque. The Reset() method does not depend on data types of a collection and could easily have been implemented.
The workaround is to execute the required GetEnumerator method again. That will require making the source object accessible when otherwise it would not have been needed.
Subarrays have no C# value
The multidimensional arrays of C# are supposed to be reference types but behave more like value types. In ASP.NET 2.0, C# is unable to generate subarrays, as in the following example:
int[,] iaValues = { {1, 2}, {3, 4} };
foreach (int iElement in iaValues)
. . .
An attempt to specify "int[] iaSubarray" instead of "int iElement" will fail with a compiler diagnostic. This burdens the programmer to subdivide the array.
As often happens, Microsoft ASP.NET 2.0 documentation is opaque on the order of elements delivered by "foreach" or by an Enumerator. Experimental programming shows that delivery is with last subscript varying most rapidly, first subscript least rapidly, sometimes called "row-wise" by those who think that the first of two dimensions must represent a row index. For the above example, delivery is in the order 1, 2, 3, 4.
int[,] iaValues = { {1, 2}, {3, 4} };
foreach (int iElement in iaValues)
. . .
An attempt to specify "int[] iaSubarray" instead of "int iElement" will fail with a compiler diagnostic. This burdens the programmer to subdivide the array.
As often happens, Microsoft ASP.NET 2.0 documentation is opaque on the order of elements delivered by "foreach" or by an Enumerator. Experimental programming shows that delivery is with last subscript varying most rapidly, first subscript least rapidly, sometimes called "row-wise" by those who think that the first of two dimensions must represent a row index. For the above example, delivery is in the order 1, 2, 3, 4.
Enumerators to nowhere
ASP.NET 2.0 Enumerator objects and their derivatives can point to nowhere. That is their initial state when created by GetEnumerator() methods on collection objects, and it is their final state after moving through all the items of a collection. Evaluating an Enumerator to nowhere will lead to an exception. How does one otherwise detect that an Enumerator points to nowhere?
As often happens, Microsoft ASP.NET 2.0 documentation is opaque. However, it offers a hint that while the Current property of an Enumerator to nowhere provides a valid KeyValuePair, the Value property of that object is undefined.
Although Microsoft does not document this, when the type of Key is numeric, the Key value will be zero; and when it is a string, the Key value will be empty. That behavior does not suffice, since such Key values might be allowed.
To detect an Enumerator to nowhere, the reliable approach is to test the Value property of Current for null, as in this abbreviated example:
SortedDictionary<...> oMap = new SortedDictionary<...>();
SortedDictionary<...>.Enumerator oMapEnum = oMap.GetEnumerator();
if (oMapEnum.Current.Value == null)
. . .
As often happens, Microsoft ASP.NET 2.0 documentation is opaque. However, it offers a hint that while the Current property of an Enumerator to nowhere provides a valid KeyValuePair, the Value property of that object is undefined.
Although Microsoft does not document this, when the type of Key is numeric, the Key value will be zero; and when it is a string, the Key value will be empty. That behavior does not suffice, since such Key values might be allowed.
To detect an Enumerator to nowhere, the reliable approach is to test the Value property of Current for null, as in this abbreviated example:
SortedDictionary<...> oMap = new SortedDictionary<...>();
SortedDictionary<...>.Enumerator oMapEnum = oMap.GetEnumerator();
if (oMapEnum.Current.Value == null)
. . .
Tuesday, March 07, 2006
Associative arrays: form over substance
The ASP.NET 2.0 Dictionary and Hashtable objects provide the form of associative arrays without guaranteeing the substance. The main objective of conventional implementations has always been to provide rapid insertion and retrieval.
Dictionary and Hashtable objects are containers of (key, value) pairs, and they provide the semantics of associative arrays. If oTable is one of these, then oTable[qKey] retrieves a value that has been associated with a key.
Conventional implementations of associative arrays maintain binary indexes and provide rapid insertion and retrieval using binary search. In its C++ library, Microsoft provides map<> containers committed to these O(log n) levels of performance.
Bjarne Stroustrop has a concise summary of C++ container performance guarantees in his book, "The C++ Programming Language," Third Edition, p. 464. David Musser and Atul Saini explain the meaning of such performance guarantees in their book, "STL Tutorial and Reference Guide," pp. 12-15.
By comparison, Microsoft documentation of ASP.NET 2.0 is scattered and opaque. Because of that, the programmer who needs O(log n) performance for both insertion and retrieval is forced to carry out performance testing and may have to write what should be, and in other environments what is, a standard library class.
Dictionary and Hashtable objects are containers of (key, value) pairs, and they provide the semantics of associative arrays. If oTable is one of these, then oTable[qKey] retrieves a value that has been associated with a key.
Conventional implementations of associative arrays maintain binary indexes and provide rapid insertion and retrieval using binary search. In its C++ library, Microsoft provides map<> containers committed to these O(log n) levels of performance.
Bjarne Stroustrop has a concise summary of C++ container performance guarantees in his book, "The C++ Programming Language," Third Edition, p. 464. David Musser and Atul Saini explain the meaning of such performance guarantees in their book, "STL Tutorial and Reference Guide," pp. 12-15.
By comparison, Microsoft documentation of ASP.NET 2.0 is scattered and opaque. Because of that, the programmer who needs O(log n) performance for both insertion and retrieval is forced to carry out performance testing and may have to write what should be, and in other environments what is, a standard library class.
Sunday, March 05, 2006
Trigger ValidationSummary popup?
A ValidationSummary control collects the ErrorMessage fields from all active validator objects in its group that have IsValid==false and displays them when it is triggered, typically by a Button. In many situations a ShowMessageBox popup message box is required.
However, when there is a CustomValidator using server-side validation in its group, it does not have the result from this validator available at postback, and it will not display a popup message for it at this time.
Upon redisplay of a page after postback, if the CustomValidator.IsValid was set to false at the server, then the message from that CustomValidator is displayed, but no popup message box is displayed by the ValidationSummary.
Is there a way to trigger the ValidationSummary control to display a popup message box after server-side validation?
However, when there is a CustomValidator using server-side validation in its group, it does not have the result from this validator available at postback, and it will not display a popup message for it at this time.
Upon redisplay of a page after postback, if the CustomValidator.IsValid was set to false at the server, then the message from that CustomValidator is displayed, but no popup message box is displayed by the ValidationSummary.
Is there a way to trigger the ValidationSummary control to display a popup message box after server-side validation?
Subscribe to Posts [Atom]