|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
BackgroundA class reference may be (For the example snippets, we'll assume that returning The naive thing to do in such cases is to simply allow .NET to throw a public int CountOccurrences ( string String1 , string String2 )
{
// Count the number of times String2 occurs in String1 and return that value
}
But this doesn't tell the calling method which value is A smarter technique is to test the passed references, and throw a more informative exception: public int CountOccurrences ( string String1 , string String2 )
{
if ( String1 == null )
{
throw new System.ArgumentNullException
( "String1" , "You must provide a string to search" ) ;
}
if ( String2 == null )
{
throw new System.ArgumentNullException
( "String2" , "You must provide a string to find" ) ;
}
// Count the number of times String2 occurs in String1 and return that value
}
But this performs the check on each parameter every time the method is called. The test for What if we could write the method as simply as the first example, but with the safety of the second? Maybe something like this: public int CountOccurrences ( NonNullable<string> String1, NonNullable<string> String2 )
{
// Count the number of times String2 occurs in String1 and return that value
}
Implementation of My NonNullable<T> StructureUnlike classes, public struct NonNullable<T> where T : class
{
// Members
}
The public readonly T Value ;
Only one constructor is required; it'll simply perform the check for public NonNullable
(
T Value
)
{
if ( Value == null )
{
throw ( new System.ArgumentNullException ( "Value" , "That value is null" ) ) ;
}
this.Value = Value ;
return ;
}
On second thoughts, many people don't like constructors that throw exceptions, so let's write one that won't public NonNullable
(
T Value
,
NonNullable<T> IfNull
)
{
if ( Value == null )
{
this.Value = IfNull.Value ;
}
else
{
this.Value = Value ;
}
return ;
}
Every type should override public override string
ToString
(
)
{
return ( this.Value.ToString() ) ;
}
By adding an implicit conversion to public static implicit operator NonNullable<T>
(
T Value
)
{
return ( new NonNullable<T> ( Value ) ) ;
}
However, there is a performance hit involved. Worse than that, the guidelines for implicit conversions state that they shouldn't throw exceptions, and this one may. And, as with the naive non-checking method, the caller won't know which parameter was Add an implicit conversion from public static implicit operator T
(
NonNullable<T> Value
)
{
return ( Value.Value ) ;
}
Lastly, a pair of public static NonNullable<T>
Coalesce
(
params T[] Values
)
{
return ( Coalesce ( (System.Collections.Generic.IEnumerable<T>) Values ) ) ;
}
public static NonNullable<T>
Coalesce
(
System.Collections.Generic.IEnumerable<T> Values
)
{
if ( Values == null )
{
throw ( new System.ArgumentNullException
( "Values", "No values were provided" ) ) ;
}
foreach ( T t in Values )
{
if ( t != null )
{
return ( new NonNullable<T> ( t ) ) ;
}
}
throw ( new System.ArgumentException
( "No non-null values were provided" , "Values" ) ) ;
}
Using the CodeMethods can be written as in the third snippet above: public int CountOccurrences
( NonNullable<string> String1 , NonNullable<string> String2 )
{
// Count the number of times String2 occurs in String1 and return that value
}
And because I included the implicit conversion, the calling method doesn't need to know what the called method is doing. In fact, the called method could be rewritten to use A better practice, when calling a method that takes ...
int count = 0 ;
string line ;
// Check this value only once!
NonNullable<string> safetext = new NonNullable<string> ( text ) ;
NonNullable<string> safeline
while ( ( line = file.Read() ) != null )
{
safeline = new NonNullable<string> ( line )
count += CountOccurrences ( safeline , safetext ) ;
}
...
(Note to self: Test with PerformanceAs stated above, this technique is not intended to improve performance; it is meant to reduce code and therefore maintenance. Having said that; my testing has shown a modest improvement in performance at best and a considerable performance hit at worst. After ten million calls to a method-that-takes-a- x 10000000 00:00:00.1204537 // with no check
x 10000000 00:00:00.1416811 // check the parameter on each call
x 10000000 00:00:00.3597213 // implicit conversion to NonNullable<string> on each call
x 10000000 00:00:00.2382019 // direct call to the NonNullable<string> constructor
// on each call
x 10000000 00:00:00.1083238 // call the NonNullable<string> constructor once
History
|
||||||||||||||||||||||