The 8- and 16-bit integral types are: byte
, sbyte
, short
, and ushort
.
C# implicitly converts them to larger types as required.
*** This can cause a compile-time error when trying to assign the result back to a small integral type:
short x = 1, y = 1;
short z = x + y; // Compile-time error
x
and y
are implicitly converted to int
so that the addition can be performed.int
, which cannot be implicitly cast back to a short
.To make this compile, we must add an explicit cast:
short z = (short) (x + y);
Floating-point types have special values to deal with the results of certain operations.
These special values are:
The float and double types have constants for NaN, +Infinity, and -Infinity.
The constants that represent special values for double and float are as follows:
Special value | Double constant | Float constant |
---|---|---|
NaN | double.NaN | float.NaN |
+infinity | double.PositiveInfinity | float.PositiveInfinity |
-infinity | double.NegativeInfinity | float.NegativeInfinity |
-0 | -0.0 | -0.0f |
For example, you can output the value of Negative Infinity in double:
Console.WriteLine (double.NegativeInfinity); // -Infinity
** Dividing a nonzero number by zero results in an infinite value.
For example:
Console.WriteLine ( 1.0 / 0.0); // Infinity
Console.WriteLine (-1.0 / 0.0); // -Infinity
Console.WriteLine ( 1.0 / -0.0); // -Infinity
Console.WriteLine (-1.0 / -0.0); // Infinity
** Dividing zero by zero, or subtracting infinity from infinity, results in a NaN.
For example:
Console.WriteLine ( 0.0 / 0.0); // NaN
Console.WriteLine ((1.0 / 0.0) - (1.0 / 0.0)); // NaN
** When using ==, a NaN value is never equal to another value, even another NaN value:
Console.WriteLine (0.0 / 0.0 == double.NaN); // False
** To test whether a value is NaN, you must use the float.IsNaN or double.IsNaN method:
Console.WriteLine (double.IsNaN (0.0 / 0.0)); // True
** When using object.Equals
, however, two NaN values are equal:
Console.WriteLine (object.Equals (0.0 / 0.0, double.NaN)); // True
Example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(1.0 / 0.0); // Infinity
Console.WriteLine(-1.0 / 0.0); // -Infinity
Console.WriteLine(1.0 / -0.0); // -Infinity
Console.WriteLine(-1.0 / -0.0); // Infinity
Console.WriteLine(0.0 / 0.0); // NaN
Console.WriteLine((1.0 / 0.0) - (1.0 / 0.0)); // NaN
Console.WriteLine(0.0 / 0.0 == double.NaN); // False
Console.WriteLine(double.IsNaN(0.0 / 0.0)); // True
Console.WriteLine(object.Equals(0.0 / 0.0, double.NaN)); // True
Console.ReadLine();
}
}
}
Output:
+0
, -0
, +Infinity
, -Infinity
, and NaN
.*** During the calculation, decimal is slower than double.
The following table summarizes all the data type convert options:
Task | Functions | Examples |
---|---|---|
Parsing base 10 numbers | Parse TryParse |
|
Parsing from base 2, 8, or 16 | Convert.ToIntegral |
|
Formatting to hexadecimal | ToString |
|
Lossless numeric conversion | Implicit cast |
|
Truncating numeric conversion | Explicit cast |
|
Rounding numeric conversion (real to integral) | Convert.ToIntegral |
|
object
or System.Object
is the ultimate base class for all types.
Any type can be upcast to object
.
The following code creates a class Stack to provide a First-In-Last_Out data structure.
public class Stack {
int position;
object[] data = new object[10];
public void Push (object obj) { data[position++] = obj; }
public object Pop() { return data[--position]; }
}
Because Stack
works with the object
type, we can Push and Pop any type to and from the Stack.
Stack stack = new Stack();
stack.Push ("CSS");
string s = (string) stack.Pop(); // Downcast, so explicit cast is needed
Console.WriteLine (s);
*** When casting between a value
type and object
, the CLR must perform the process of boxing and unboxing.
Boxing is the process of converting a value-type to a reference-type, which can be either the object class or an interface.
In the following code, we box an int into an object:
int x = 1;
object obj = x; // Box the int
Unboxing is the operation of casting the object back to the original value type:
int y = (int)obj; // Unbox the int
Unboxing requires an explicit cast.
C# throws an InvalidCastException if the value type does not match the object type.
For instance, the following throws an exception, because long does not exactly match int:
object obj = 19; // 19 is inferred to be of type int
long x = (long) obj; // InvalidCastException
You change the above code to the following:
object obj = 9;
long x = (int) obj;
The following code shows how to unbox a double
value to int
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
object obj = 4.5; // 4.5 is inferred to be of type double
int x = (int)(double)obj; // x is now 4
Console.WriteLine(x);
Console.ReadLine();
}
}
}
Output: