By Jay Hilyard, Stephen Teilhet
Cover | Table of Contents | Colophon
bool type. These numeric types consist of a decimal type (decimal), nine integral types (byte, char, int, long, sbyte, short, uint, ulong, ushort), and two floating-point types (float, double). Table 1-1 lists the simple types and their fully qualified names in the .NET Framework.|
Fully qualified name
|
Alias
|
Value range
|
|---|---|---|
System.Boolean
|
bool
|
true or false
|
System.Byte
|
byte
|
0 to 255
|
System.SByte
|
sbyte
|
-128 to 127
|
System.Char
|
char
|
0 to 65535
|
bool type. These numeric types consist of a decimal type (decimal), nine integral types (byte, char, int, long, sbyte, short, uint, ulong, ushort), and two floating-point types (float, double). Table 1-1 lists the simple types and their fully qualified names in the .NET Framework.|
Fully qualified name
|
Alias
|
Value range
|
|---|---|---|
System.Boolean
|
bool
|
true or false
|
System.Byte
|
byte
|
0 to 255
|
System.SByte
|
sbyte
|
-128 to 127
|
System.Char
|
char
|
0 to 65535
|
double or float to determine whether they are within a close approximation to each other. Take, for example, the result of comparing the expression 1/6 and the value 0.16666667. These seem to be equivalent, except that 0.16666667 is precise to only eight places to the right of the decimal point, and 1/6 is precise to the maximum number of digits to the right of the decimal point that the data type will hold. using System;
// Override that uses the System.Double.Epsilon value
public static bool IsApproximatelyEqualTo(double numerator,
double denominator,
double dblValue)
{
return IsApproximatelyEqualTo(numerator,
denominator, dblValue, double.Epsilon);
}
// Override that allows for specification of an epsilon value
// other than System.Double.Epsilon
public static bool IsApproximatelyEqualTo(double numerator,
double denominator,
double dblValue,
double epsilon)
{
double difference = (numerator/denominator) - dblValue;
if (Math.Abs(difference) < epsilon)
{
// This is a good approximation.
return true;
}
else
{
// This is NOT a good approximation.
return false;
}
}double with float allows you to determine whether a fraction and a float value are approximately equal.Math class, all units are in radians. You have one or more angles measured in degrees and want to convert these to radians in order to use them with the members of the Math class. using System;
public static double ConvertDegreesToRadians (double degrees)
{
double radians = (Math.PI / 180) * degrees;
return (radians);
}Math class use radians as their unit of measure for angles. It is very handy to have conversion routines to convert between radians and degrees, especially when a user is required to enter data in degrees rather than radians. After all, humans understand degrees better than radians.radians = (Math.PI / 180) * degrees
Math.PI contains the constant π.Math class, all units are in radians; instead, you require a result in degrees. using System;
public static double ConvertRadiansToDegrees(double radians)
{
double degrees = (180 / Math.PI) * radians;
return (degrees);
}Math class use radians as their unit of measure for angles. It is very handy to have conversion routines to convert between radians and degrees; displaying degrees to a user is more informative than displaying radians.degrees = (180 / Math.PI) * radians
Math.PI contains the constant π.int, uint, long, ulong, and enumeration data types consisting of the underlying types int, uint, long, and ulong. However, you need to perform a bitwise complement operation on a different numeric data type.byte data type:byte y = 1; byte result = (byte)~y;
result is 254.byte data type: byte y = 1;
Console.WriteLine("~y = " + ~y);-2
byte variable is incorrect; it should be 254. In fact, byte is an unsigned data type, so it cannot be equal to a negative number. If you rewrite the code as follows:byte y = 1; byte result = ~y;
byte before you assign it to the result variable, as shown here:byte y = 1; byte result = (byte)~y;
int, uint, long, ulong, bool, and enumeration data types. When one of the bitwise operators is used on another data type, that data type is converted to the supported data type that matches it most closely. Therefore, a byte data type is converted to an int before the bitwise complement operator is evaluated:0x01 // byte y = 1; 0xFFFFFFFE // The value 01h is converted to an int and its // bitwise complement is taken. // This bit pattern equals -2 as an int. 0xFE // The resultant int value is cast to its original byte data type.
int data type is a signed data type, unlike the public static boolIsEven(int intValue)
{
return ((intValue % 2) == 0);
} public static boolIsOdd(int intValue)
{
return ((intValue % 2) == 1);
}1. Therefore, by checking whether this bit is equal to 1, you can tell whether it is an odd number. Conversely, testing the least-significant bit to see whether it is 0 can tell you whether it is an even number.1 and then determine whether the result is equal to zero. If it is, you know that the value is an even number; otherwise, the value is odd. This operation is part of the IsEven method.1, similar to how the even test operates, and then determine whether the result is 1. If so, you know that the value is an odd number; otherwise, the value is even. This operation is part of the IsOdd method.IsEven and IsOdd methods in your application, although implementing both methods might improve the readability of your code. You can implement one in terms of the other. For example, here is an implementation of IsOdd in terms of IsEven: public static bool IsOdd(int intValue)
{
return (!IsEven(intValue));
}IsEven method as follows: public static bool IsEven(long longValue)
{
return ((longValue & 1) == 0);
} public static intGetHighWord(int intValue)
{
return (intValue & (0xFFFF << 16));
} public static intGetLowWord(int intValue)
{
return (intValue & 0x0000FFFF);
}AND operation:uint intValue = Int32.MaxValue; uint MSB = intValue & (0xFFFF << 16); // MSB == 0xFFFF0000
ANDs the number to another number with all of the high word set to 1. This method will zero out all of the low word, leaving the high word intact.AND operation:uint intValue = Int32.MaxValue; uint LSB = intValue & 0x0000FFFF; // LSB == 0x0000FFFF
ANDs the number to another number with all of the low word set to 1, which zeros out all of the high word, leaving the low word intact.GetHighWord method as follows: public static short GetHighByte(short shortValue)
{
return (short)(shortValue & (0xFF << 8));
}GetLowWord method is modified as shown here: public static short GetLowByte(short shortValue)
{
return (short)(shortValue & (short)0xFF);
}Convert.ToInt32 method on the Convert class: string base2 = "11";
string base8 = "17";
string base10 = "110";
string base16 = "11FF";
Console.WriteLine("Convert.ToInt32(base2, 2) = " +
Convert.ToInt32(base2, 2));
Console.WriteLine("Convert.ToInt32(base8, 8) = " +
Convert.ToInt32(base8, 8));
Console.WriteLine("Convert.ToInt32(base10, 10) = " +
Convert.ToInt32(base10, 10));
Console.WriteLine("Convert.ToInt32(base16, 16) = " +
Convert.ToInt32(base16, 16));Convert.ToInt32(base2, 2) = 3 Convert.ToInt32(base8, 8) = 15 Convert.ToInt32(base10, 10) = 110 Convert.ToInt32(base16, 16) = 4607
Convert.ToInt32 method has an overload that takes a string containing a number and an integer defining the base of this number. This method then converts the numeric string into an integer. Console.WriteLine then converts the number to base10 and displays it.Convert class, such as
ToByte, ToInt64, and ToInt16, also have this same overload, which accepts a number as a string and the base in which this number is expressed. Unfortunately, these methods convert from a string value expressed in base2, base8, base10, and base16 only. They do not allow for converting a value to a string expressed in any other base types than base10. However, the
ToString methods on the various numeric types do allow for this conversion.
TryParse method of any of the numeric types. For example, to determine whether a string contains a double, use the following method: string str = "12.5";
double result = 0;
if(double.TryParse(str,
System.Globalization.NumberStyles.Float,
System.Globalization.NumberFormatInfo.CurrentInfo,
out result))
{
// Is a double!
}TryParse method returns true if the string contains a valid number without the exception that you will get if you use the Parse method. Since TryParse does not throw exceptions, it performs better over time given a set of strings where some do not contain numbers.Math.Round method, which takes only a single argument:int x = (int)Math.Round(2.5555); // x == 3
Math.Round method, which takes two arguments:decimal x = Math.Round(2.5555, 2); // x == 2.56
Round method is easy to use; however, you need to be aware of how the rounding operation works. The Round method follows the IEEE Standard 754, section 4 standard. This means that if the number being rounded is halfway between two numbers, the Round operation will always round to the even number. An example will show what this means to you:decimal x = Math.Round(1.5); // x == 2 decimal y = Math.Round(2.5); // y == 2
1.5 is rounded up to the nearest even whole number and 2.5 is rounded down to the nearest even whole number. Keep this in mind when using the Round method.Math.Round method will round the value 1.5 to 2; however, the value 2.5 will also be rounded to 2 using this method. You may always want to round to the greater number in this type of situation (e.g., round 2.5 to 3 instead of 2). Conversely, you might want to always round to the lesser number (e.g., round 1.5 to 1).Math.Floor method to always round up when a value is halfway between two whole numbers: public static double RoundUp(double valueToRound)
{
return (Math.Floor(valueToRound + 0.5));
} public static double RoundDown(double valueToRound)
{
double floorValue = Math.Floor(valueToRound);
if ((valueToRound - floorValue) > .5)
{
return (floorValue + 1);
}
else
{
return (floorValue);
}
}Math.Round method rounds to the nearest even number (see Recipe 1.9 for more information). However, there are some times that you do not want to round a number in this manner. The static Math.Floor method can be used to allow for different manners of rounding. public static double CtoF(double celsius)
{
return (((0.9/0.5) * celsius) + 32);
}TempFahrenheit = ((9 / 5) * TempCelsius) + 32
public static double FtoC(double fahrenheit)
{
return ((0.5/0.9) * (fahrenheit - 32));
}TempCelsius = (5 / 9) * (TempFahrenheit - 32)
long to an int results in a loss of information only if the long data type is greater than int.MaxSize.
checked keyword. The following method accepts two long data types and attempts to add them together. The result is stuffed into an int data type. If an overflow condition exists, the
OverflowException is thrown: using System;
public void UseChecked(long lhs, long rhs)
{
int result = 0;
try
{
result = checked((int)(lhs + rhs));
}
catch (OverflowException e)
{
// Handle overflow exception here.
}
}try/catch blocks to handle the overflow condition, you can use the
MaxValue and
MinValue fields of each type. A check using these fields can be done prior to the conversion to insure that no loss of information occurs. If this does occur, the code can inform the application that this cast will cause a loss of information. You can use the following conditional statement to determine whether sourceValue can be cast to a short without losing any information: // Our two variables are declared and initialized.
int sourceValue = 34000;
short destinationValue = 0;
// Determine if sourceValue will lose information in a cast to a short.
if (sourceValue <= short.MaxValue && sourceValue >= short.MinValue)
{
destinationValue = (short)sourceValue;
}
else
{
// Inform the application that a loss of information will occur.
}Int32 to a value of type Int16. If the Int32 value is smaller than or equal to the Int16.MaxValue field and the Int32 value is higher than or equal to the Math.Sin, Math.Cos, and Math.Tan methods of the Math class to find the length of one side. The equations for these methods are as follows:double theta = 40; doublehypotenuse = 5; double oppositeSide = 0; double adjacentSide = 0; oppositeSide = Math.Sin(theta) * hypotenuse; oppositeSide = Math.Tan(theta) * adjacentSide; adjacentSide = Math.Cos(theta) * hypotenuse; adjacentSide = oppositeSide / Math.Tan(theta); hypotenuse = oppositeSide / Math.Sin(theta); hypotenuse = adjacentSide / Math.Cos(theta);
theta (Θ) is the known angle, the oppositeSide variable is equal to the length of the side opposite to the angle theta, and the adjacentSide variable is equal to the length of the side adjacent to the angle theta. The hypotenuse variable is equal to the length of the hypotenuse of the triangle. See Figure 1-1.
Math.Sqrt static method, as follows:double hypotenuse = Math.Sqrt((xSide * xSide) + (ySide * ySide));
xSide and ySide are the lengths of the two sides that are not the hypotenuse of the triangle.sin(Theta) = oppositeSide / hypotenuseSide cos(Theta) = adjacentSide / hypotenuseSide tan(Theta) = oppositeSide / adjacentSide
theta is the value of the known angle. Rearranging these equations allows you to derive the following equations:Math.Atan, Math.Acos, or Math.Asin static methods of the Math class. The following code calculates the angle theta and returns the value in radians:double theta = Math.Atan(OppositeSide / AdjacentSide); theta = Math.Acos(AdjacentSide / Hypotenuse); theta = Math.Asin(OppositeSide / Hypotenuse);
double theta = Math.Atan(oppositeSide / adjacentSide) * (180 / Math.PI); theta = Math.Acos(adjacentSide / hypotenuse) * (180 / Math.PI); theta = Math.Asin(oppositeSide / hypotenuse) * (180 / Math.PI);
theta is the known angle value, oppositeSide is equal to the length of the side opposite to the angle, and adjacentSide is equal to the length of the side adjacent to the angle. The hypotenuse is the length of the hypotenuse of the triangle. See Figure 1-1 in Recipe 1.14 for a graphical representation of these sides of a right triangle and Recipes 1.2 and 1.3 for converting between degrees and radians.Math.Atan, Math.Acos, and Math.Asin on the Math class provide the functionality to implement these trigonometric operations.ToString method that each enumeration member inherits from System.Enum.ValidShape enumeration type as an example, you can obtain the textual and numeric values so that you can display them: enum ValidShape
{
Square, Circle, Cylinder, Octagon
}ToString method of the ValidShape enumeration type, you can derive the value of a specific ValidShape enumeration value directly: Console.WriteLine(ValidShape.Circle.ToString());
Console.WriteLine(ValidShape.Circle.ToString("G"));
Console.WriteLine(ValidShape.Circle.ToString("D"));
Console.WriteLine(ValidShape.Circle.ToString("F"));
Console.WriteLine(ValidShape.Circle.ToString("X"));Circle Circle 1 Circle 00000001
ValidShape, the enumeration values can be derived in the same manner: ValidShape shapeStyle = ValidShape.Cylinder;
Console.WriteLine(shapeStyle.ToString());
Console.WriteLine(shapeStyle.ToString("G"));
Console.WriteLine(shapeStyle.ToString("D"));
Console.WriteLine(shapeStyle.ToString("F"));
Console.WriteLine(shapeStyle.ToString("X"));Cylinder Cylinder 2 Cylinder 00000002
ToString instance method on the Enum type. This method can accept a character indicating the type of formatting to place on the enumeration value. The character can be one of the following: G, g, D, d, X, x, F, or f. See Table 1-2 for a description of these formatting types.|
Formatting type
|
Name
|
Description
|
|---|---|---|
|
G or g
|
(General)
|
Parse method on the Enum class allows the textual value of an enumeration element to be converted to a usable enumeration value. For example: try
{
Language proj1Language = (Language)Enum.Parse(typeof(Language),
"VBNET");
Language proj2Language = (Language)Enum.Parse(typeof(Language),
"UnDefined");
}
catch (ArgumentException e)
{
// Handle an invalid text value here
//(such as the "UnDefined" string)
}Language enumeration is defined as: enum Language
{
Other = 0, CSharp = 1, VBNET = 2, VB6 = 3
}Enum.Parse method converts text to a specific enumeration value. This technique is useful when a user is presented a list of values, with each value defined in an enumeration. When the user selects an item from this list, the text chosen can be easily converted from its string representation to its equivalent enumeration value using Enum.Parse. This method returns an object, which must then be cast to the target enum type in order to use it.Enum.Parse a single enumeration value as a string, you can also pass the enumeration value as its corresponding numeric value. For example, consider the following line:Language proj1Language = (Language)Enum.Parse(typeof(Language), "VBNET");
Language proj1Language = (Language)Enum.Parse(typeof(Language), "2");
Language.VBNET enumeration value is equal to 2.Parse method is that it can accept a comma-delimited list of enumeration names or values and then logically OR them together. The following example creates an enumeration with the languages VBNET and CSharp ORed together:Language proj1Language = (Language)Enum.Parse(typeof(Language), "CSharp, VBNET");
switch statement to list the values. enum Language
{
Other = 0, CSharp = 1, VBNET = 2, VB6 = 3
}Language enumeration, such as the following method: public void HandleEnum(Language language)
{
// Use language here…
}HandleEnum. The CheckLanguageEnumValue method shown here does that: public static bool CheckLanguageEnumValue(Language language)
{
switch (language)
{
// All valid typesfor the enum listed here
// This means only the ones we specify are valid.
// Not any enum value for this enum
case Language.CSharp:
case Language.Other:
case Language.VB6:
case Language.VBNET:
break;
default:
Debug.Assert(false, language +
" is not a valid enumeration value to pass.");
return false;
}
return true;
}Enum class contains the static
IsDefined method, it should not be used. IsDefined uses reflection internally, which incurs a performance penalty. Also, versioning of the enumeration is not handled well. Consider the scenario in which you add the value MgdCpp (managed C++) to the Languages enum in the next version of your software. If IsDefined is used to check the argument here, it will allow MgdCpp as a valid value, since it is defined in the enumeration, even though the code for which you are validating the parameter is not designed to handle it. By being specific with the switch statement shown in CheckLanguageEnumValue, you reject the MgdCppFlags attribute).All member to the existing enumeration equal to all the members of the enumeration ORed together. Then use the
HandleFlagsEnum method to do the test.Enum.IsDefined with an enumeration marked with the Flags attribute. Consider if the Language enumeration was written as follows: [Flags]
enum Language
{
CSharp = 1, VBNET = 2, VB6 = 4
}Language are the set of numbers {1, 2, 3, 4, 5, 6, 7}. However, the values 3, 5, 6, and 7 are not explicitly represented in this enumeration. The value 3 is equal to the CSharp and VBNET enumeration members ORed together, and the value 7 is equal to all of the enumeration members ORed together. For the values 3, 5, 6, and 7, the Enum.IsDefined method will return false, indicating that these are not valid values, when in fact they are. You need a way to determine if a correct set of flags has been passed into a method.Language enumeration to define all values for which the Language enumeration is valid. In this case, the Language enumeration would be rewritten as: [Flags]
enum Language
{
CSharp = 1, VBNET = 2, VB6 = 4,
All = (CSharp | VBNET | VB6)
}All enumeration member is equal to all other Language members ORed together. Now, when you want to validate a Language flag, all you have to do is the following: public bool HandleFlagsEnum(Language language)
{
if ((language != 0) && ((language & Language.All) == language))
{
return (true);
}
else
{
return (false);
}
}HandleFlagsEnum method with existing code, all that is required is to add an All member to the existing enumeration. The All member should be equal to all the members of the enumeration ORed together. [Flags]
enum Language
{
CSharp = 0x0001, VBNET = 0x0002, VB6 = 0x0004, Cpp = 0x0008
}Language lang = Language.CSharp | Language.VBNET;
Flags attribute to an enumeration marks this enumeration as individual bit flags that can be ORed together. Using an enumeration of flags is no different than using a regular enumeration type. It should be noted that failing to mark an enumeration with the Flags attribute will not generate an exception or a compiletime error, even if the enumeration values are used as bit flags.Flags attribute provides you with two benefits. First, if the Flags attribute is placed on an enumeration, the ToString and ToString("G") methods return a string consisting of the name of the constant(s) separated by commas. Otherwise, these two methods return the numeric representation of the enumeration value. Note that the ToString("F") method returns a string consisting of the name of the constant(s) separated by commas, regardless of whether this enumeration is marked with the Flags attribute. For an indication of why this works in this manner, see the "F" formatting type in Table 1-2 in Recipe 1.16.Flags attribute), you can use it as such.Flags attribute can be viewed as a single value or as one or more values combined into a single enumeration value. If you need to accept multiple languages at a single time, you can write the following code:Language lang = Language.CSharp | Language.VBNET;
lang is now equal to the bit values of the two enumeration values ORed together. These values ORed together will equal 3, as shown here:Language: [Flags]
enum Language
{
CSharp = 0x0001, VBNET = 0x0002, VB6 = 0x0004, Cpp = 0x0008
}lang in the following line of code contains a language such as Language.CSharp and/or Language.Cpp:Language lang = Language.CSharp | Language.VBNET;
if((lang & Language.CSharp) == Language.CSharp)
{
// Lang contains at least Language.CSharp.
} if(lang == Language.CSharp)
{
// lang contains only the Language.CSharp.
} if((lang & (Language.CSharp | Language.VBNET)) ==
(Language.CSharp | Language.VBNET))
{
// lang contains at least Language.CSharp and Language.VBNET.
} if((lang | (Language.CSharp | Language.VBNET)) ==
(Language.CSharp | Language.VBNET))
{
// lang contains only the Language.CSharp and Language.VBNET.
}Flags attribute, they usually will require some kind of conditional testing to be performed. This testing necessitates the use of the bitwise AND (&) and OR (|) operators.if((lang & Language.CSharp) == Language.CSharp)
lang is of the Language enumeration type.& operator is used with a bit mask to determine if a bit is set to 1. The result of ANDing two bits is 1 only when both bits are 1; otherwise, the result is 0. You can use this operation to determine if a specific bit flag is set to a 1 in the number containing the individual bit flags. If you AND the variable decimal or double number.decimal or double by truncating it to the whole number closest to zero. To do so, use the overloaded static System.Math.Truncate method, which takes either a decimal or a double as an argument and returns the same type:decimal pi = (decimal)System.Math.PI; decimal decRet = System.Math.Truncate(pi); // decRet = 3 double trouble = 5.555; double dblRet = System.Math.Truncate(trouble);
Truncate method is new in the 2.0 version of the Framework and helps to "round" out the mathematical capabilities of the Framework. The Truncate method has the net effect of simply dropping the fractional portion of the number and returning the integral part. Once floating-point numbers get over a certain size, they do not actually have a fractional part, but have only an approximate representation of their integer portion.System.String type does not derive from System.ValueType and is therefore considered a reference type. The string alias is built into C# and can be used instead of the full name.String class; there is also a System.Text.StringBuilder class for performing string manipulations and the
System.Text.RegularExpressions
namespace for searching strings. This chapter will cover the String class and the System.Text.StringBuilder class.System.Text.StringBuilder class provides an easy, performance-friendly method of manipulating string objects. Even though this class duplicates much of the functionality of a String class, the StringBuilder class is fundamentally different in that the string contained within the StringBuilder object can actually be modified—you cannot modify a string object. However, this duplicated functionality provides a more efficient manipulation of strings than is obtainable by using the String class.char and wish to determine the kind of character it contains—a letter, digit, number, punctuation character, control character, separator character, symbol, whitespace, or surrogate character. Similarly, you have a string variable and want to determine the kind of character in one or more positions within this string.char, use the built-in static methods on the System.Char structure shown here:Char.IsControl Char.IsDigit Char.IsLetter Char.IsNumber Char.IsPunctuation Char.IsSeparator Char.IsSurrogate Char.IsSymbol Char.IsWhitespace
public enumCharKind
{
Letter,
Number,
Punctuation,
Unknown
}CharKindSystem.String type does not derive from System.ValueType and is therefore considered a reference type. The string alias is built into C# and can be used instead of the full name.String class; there is also a System.Text.StringBuilder class for performing string manipulations and the
System.Text.RegularExpressions
namespace for searching strings. This chapter will cover the String class and the System.Text.StringBuilder class.System.Text.StringBuilder class provides an easy, performance-friendly method of manipulating string objects. Even though this class duplicates much of the functionality of a String class, the StringBuilder class is fundamentally different in that the string contained within the StringBuilder object can actually be modified—you cannot modify a string object. However, this duplicated functionality provides a more efficient manipulation of strings than is obtainable by using the String class.char and wish to determine the kind of character it contains—a letter, digit, number, punctuation character, control character, separator character, symbol, whitespace, or surrogate character. Similarly, you have a string variable and want to determine the kind of character in one or more positions within this string.char, use the built-in static methods on the System.Char structure shown here:Char.IsControl Char.IsDigit Char.IsLetter Char.IsNumber Char.IsPunctuation Char.IsSeparator Char.IsSurrogate Char.IsSymbol Char.IsWhitespace
public enumCharKind
{
Letter,
Number,
Punctuation,
Unknown
}CharKind enumeration value indicating that type: public static CharKindGetCharKind(char theChar)
{
if (Char.IsLetter(theChar))
{
return CharKind.Letter;
}
else if (Char.IsNumber(theChar))
{
return CharKind.Number;
}
else if (Char.IsPunctuation(theChar))
{
return CharKind.Punctuation;
}
else
{
return CharKind.Unknown;
}
}char structure. The following code modifies the GetCharKind method to accept a string variable and a character position in that string. The character position determines which character in the string is evaluated. public static CharKind GetCharKindInString(string theString, int charPosition)
{
if (Char.IsLetter(theString, charPosition))
{
return CharKind.Letter;
}
else if (Char.IsNumber(theString, charPosition))
{
return CharKind.Number;
}
else if (Char.IsPunctuation(theString, charPosition))
{
return CharKind.Punctuation;
}
else
{
return CharKind.Unknown;
}
}char data type is within a range, such as between the numbers 1 and 5 or between the letters A and M.char data type. The following code shows how to use the built-in comparison support: public static boolIsInRange(char testChar, char startOfRange, char endOfRange)
{
if (testChar >= startOfRange && testChar <= endOfRange)
{
// testChar is within the range.
return (true);
}
else
{
// testChar is NOT within the range.
return (false);
}
}startOfRange and endOfRange
characters have different cases, the result m