#95 – ToString() Called Automatically When Doing String Concatenation

When doing string concatenation, either using the + operator or when using the String.Concat or String.Format methods, you can concatenate objects that are not strings.  .NET will attempt to convert these objects to strings before doing the concatenation by calling the object’s ToString method.

Here’s an example:

string s1 = "Ten: " + 10;   // Ten: 10

This is equivalent to:

 int n = 10;
 string s1 = "Ten: " + n.ToString();

This works for any object:

 DateTime dt = DateTime.Now;
 string s2 = "Date and time: " + dt;

This causes the DateTime.ToString method to be called, which results in a string that looks like:

Date and time: 9/16/2010 4:01:44 PM

#94 – Converting Between Char and Numeric Types

You can implicitly convert from char to any numeric type that can store values in the range [0,65535].  This means that you can convert to int implicitly, as well as ushort, but not to short.

 char c1 = 'X';
 int n1 = c1;     // Implicit conversion to numeric
 ushort s1 = c1;  // Also works
 short s2 = c1;   // Implicit not allowed, must cast
 byte b = c1;     // Implicit not allowed, must cast

You can also convert from a numeric type to a char, but no implicit conversion exists–you must always use a cast or the Convert class.

 short n2 = 90;
 char c2 = (char)n2;  // No implicit conversion, must use cast

#93 – Escape Sequences in Character Literals

Just as we can include escape sequences in string literals, we can also use escape sequences in character literals to indicate special or non-printable characters.

The list of allowed escape sequences for character literals in C# is the same as for string literals, with the exception of the 8-byte Unicode literal for surrogate pairs:

  • \a  –  Bell (alert)
  • \b  –  Backspace
  • \f  –  Formfeed
  • \n  –  New line
  • \r  –  Carriage return
  • \t  –  Horizontal tab
  • \v  –  Vertical tab
  • \’  –  Single quote
  • \”  –  Double quote
  • \\  –  Backslash
  • (backslash followed by 0) – Null
  • \xhh  –  ASCII character in hex
  • \xhhhh  –  Unicode character in hex
  • \uhhhh – Unicode character  (4-byte)

Here are some examples in code:

 char c4 = '\n';    // Newline
 char c5 = '\r';    // Carriage return
 char c6 = '\t';    // Tab
 char c8 = '\'';    // Single quote
 char c9 = '\"';    // Double quote
 char c10 = '\\';   // Backslash
 char c11 = '\0';   // Null
 char c12 = '\x2E';  // hex
 char c13 = '\xe213';  // hex

#92 – The Ternary Conditional Operator

The conditional operator (?:) take three operands.  The first is a boolean expression to evaluate. If this expression is true, the value of the conditional operator is equal to the second operand.  If it’s false, the value of the conditional operator is equal to the third operand.

So for the expression

 a ? b : c

the value of this expression is b if a is true, or c if a is false.

Here’s an example of using the conditional operator (assume that isRaining is a boolean):

string describeWeather = isRaining ? "Wet" : "Nice";

A conditional operator can always be rewritten as an if statement.  The previous example is equivalent to:

string describeWeather;
if (isRaining)
    describeWeather = "Wet";
else
    describeWeather = "Nice";

Using the conditional operator can lead to more concise code.

#91 – Conditional Operators Can Short-Circuit Evaluation

C# won’t necessarily evaluate every sub-expression in a larger expression.  If knowing the value of the first operand is sufficient for knowing the value of the entire expression, the larger expression is said to be short-circuited.

When evaluating a logical AND (&&), the second operand will not be evaluated if the first operand is false.  The entire expression is false.

bool b1 = false && expr;   // Result is false; expr never evaluated

When evaluating a logical OR (||), the second operand will not be evaluated if the first operand is true.  The entire expression is true.

bool b1 = true || expr;   // Result is true; expr never evaluated


#90 – More Complex Logical Expressions

Using the basic logical operators, you can build up more complex expressions.

bool travel = haveVacHours && (haveMoney || (canGetLoan && !tonsOfDebt));

The above expression could be read as “I will travel if I have the vacation hours and I either have money on hand or I can take out a loan and don’t already have massive debt”.

Parentheses are used to indicate precedence–i.e. which sub-expressions should be evaluated first.  In the above example, the order of evaluation is: rightmost &&, then ||, then leftmost &&.

#89 – The Negation Operator

The negation operator (!), read as “not”, performs a logical negation on its single operand.  Negating a false value yields a true value and negating a true value yields false.

 bool b1;
 b1 = !false;        // true
 b1 = !true;         // false

#88 – Conditional Operators

The conditional operators (&&, ||) allow performing a logical AND (&&) or logical OR (||) on its two boolean operands.

The AND (&&) operator returns true only if both of its operands are true.

 bool b1;
 b1 = false && false;    // false
 b1 = false && true;     // false
 b1 = true && false;     // false
 b1 = true && true;      // true

The OR (||) operator returns true if at least one of its operands is true.

 b1 = false || false;    // false
 b1 = false || true;     // true
 b1 = true || false;     // true
 b1 = true || true;      // true

You’d normally use boolean variables in expressions where conditional operators are used, e.g.:

 bool goForWalk = niceWeather && lightOutside;
 bool callPolice = seeBurglar || brokeALimb;

#87 – Relational Operators

The relational operators (<, >, <=, >=) are used to compare the values of two operands and return a boolean value based on comparing the values of the operands.

  • <       Returns true if the 1st operand is less than the 2nd
  • <=    Returns true if the 1st operand is less than or equal to the 2nd
  • >       Returns true if the 1st operand is greater than the 2nd
  • >=    Returns true if the 1st operand is greater than or equal to the 2nd

The relational operators are typically used on numeric operands (e.g. float, int).  You can also compare objects of type char and enum type members.  More generally, the operators will be available for objects of any type that implements the relational operators.

#86 – Equality and Inequality Operators

In C#, the equality and inequality operators are used to check the equivalence of two operands.  The operands can be of any type.

  • ==    Equality
  • !=      Inequality

These operators always take two operands and return a boolean value.

  • == Returns true if its operands are equal
  • != Returns true if its operands are not equal

The behavior of the operators depends on the type:

  • Value types – equal if values are equal
  • Reference types – equal if the operands point to the same object
  • string type – equal if the values are equal
  • Custom types – you can override the behavior

Examples:

// Value types
 bool b1 = (1 == 2);     // false
 int i = 12, j = 12;
 b1 = (i == j);     // true
 b1 = (i != j);     // false

 // Reference types
 Cat c1 = new Cat("Herman");
 Cat c2 = new Cat("Boris");
 Cat c3 = new Cat("Herman");
 Cat c4 = c1;
 b1 = (c1 == c2);    // false
 b1 = (c1 == c3);    // false, though same name
 b1 = (c4 == c1);    // true, both point to the same Cat