Working with System Data Types and Corresponding C# Keywords

C# defines keywords for fundamental data types, which are used to represent local variables, class data member variables, method return values, and parameters.

Rather, C# data type keywords are actually shorthand notations for full-blown types in the System namespace.

The Intrinsic Data Types of C#

C# ShorthandCLS ComplaintSystem TypeMeaning in Life
boolyesBooleanRepresents truth or falsity
sbytenoSbyteSigned 8-bit number
byteyesByteUnsigned 8-bit number
shortyesInt16Signed 16-bit number
ushortNoUInt16Unsigned 16-bit number
intyesInt32Signed 32-bit number
uintnoUInt32Unsigned 32-bit number
longyesInt64Signed 64-bit number
ulongnoUInt64Unsigned 64-bit number
charyesCharSingle 16-bit Unicode character
floatyesSingle32-bit floating point number
doubleyesDouble64-bit floating point number
decimalyesDecimal128-bit floating point number
stringyesStringRepresents a set of Unicode characters.
objectyesObjectThe base class of all types in the .NET universe.

CLS-compliant .NET Core code can be used by any other .NET programming language. If you expose non-CLS-complaint data from your programs, other .NET languages may not be able to make use of it.


Understanding Variable Declaration and Initialization

When you are declaring a local variable, you do so by specifying the data types, followed by the variable name.

// Local variables are declared as so: 
// dataType varName; 
int myInt; 
string myString; 

Be aware that it is a "compiler error" to make use of a local variable before assigning an initial value.

It is good to practice to assign an initial value to your local data points at the time of declaration.

// Local variables are declared and initialized as follows: 
// dataType varName = initialValue; 
int myInt = 10; 
 
// You can also declare and assign on 2 lines. 
string myString; 
myString = "This is my character data"; 

The default Literal (New 7.1)

The "default" literal assigns a variable the default value for its data types. This works for standard data types as well as custom classes and generic types.

int myInt = default; 


Using Intrinsic Data Types and the new Operator (Updated 9.0)

All intrinsic data types support what is known as a default constructor. This feature allows you to create a variable using the "new" keyword which automatically sets the variable to its default value.

  1. bool variables are set to false.
  2. Numeric data is set to 0 (or 0.0 for floating-point data types)
  3. char variables are set to a single empty character.
  4. BigInteger variables are set to 0.
  5. DateTime variables are set to 1/1/0001 12:00:00 AM.
  6. Object references (including strings) are set to null.

bool b = new bool(); 
int i = new int(); 
double d = new double(); 
DateTime dt = new DateTime(); 

C# 9.0 added a shortcut for creating variable instances. This shortcut is simply using the keyword new() without the data type.

bool b = new(); 
int i = new(); 
double d = new(); 
DateTime dt = new(); 

Understanding the Data Type Class Hierarchy

  1. Each type ultimately derives from System.Object
  2. Many numerical data types derive from a class named System.ValueType. Descendants of ValueType are automatically allocated on the Stack and, therefore, have a predictable lifetime and are quite efficient. On the other hand, types that do not have System.ValueType in their inheritance chain (such as System.Type, System.String, System.Array, System.Exception, and System.Delegate) are not allocated on the stack but on the garbage-collected heap.

Console.WriteLine(12.GetHashCode());// 12 
Console.WriteLine(12.Equals(25));   // False 
Console.WriteLine(12.ToString());   // 12 
Console.WriteLine(12.GetType());    // System.Int32 


Understanding the Members of Numerical Data Types

The numerical data types of .NET Core support MaxValue and MinValue properties that provide information regarding the range a given type can store.

Console.WriteLine("Max of int {0}", int.MaxValue);
Console.WriteLine("Min of int {0}", int.MinValue);

When you define a literal whole number (such as 500), the runtime will default the data type to "int".

Likewise, literal floating-point data (such as 55.333) will default to a "double".

To set the underlying data type to a long use suffix "l" or "L" (4L).

To declare a float variable, use the suffix "f" or "F" to the raw numerical value (5.3F).

Use the suffix "m" or "M" to a floating-point number to declare a decimal (300.5M).


Understanding the Members of System.Boolean

System.Boolean data type, only valid assignment a C# bool can take is from the set {true | false}.

No -> MinValue & MaxValue rather

Yes -> TrueString & FalseString (yields "True" or "False" string, respectively).

Console.WriteLine(bool.FalseString);
Console.WriteLine(bool.TrueString);


Understanding the Members of System.Char

System.Char type provides you with a great deal of functionality beyond the ability to hold a single point of character data.

Methods

IsDigit, IsLetter, IsWhiteSpace, IsPunctuation


Parsing Values from String Data

The .NET data types provide the ability to generate a variable of their underlying type given a textual equivalent.

bool b = bool.Parse("true");
double d = double.Parse("99.44");
int i = int.Parse("4");
char c = char.Parse("k");

Using TryParse to Parse Value from String Data

One issue with the preceding codes is that an exception will be thrown if the string cannot be cleanly converted to the correct data type.

// Without TryParse 
bool b = bool.Parse("Hello"); 

The TryParse() statement takes an "out" parameter and returns a bool if the parsing was successful.

// Using TryParse 
if (bool.TryParse("True", out bool b)){ 
    Console.WriteLine($"B is successfully converted to a bool : {b}") 
} 

Using System.DateTime and System.TimeSpan

The DateTime type contains data that represents a specific date (month, day, year) and time value, both of which may be formatted in a variety of ways using the supplied members. The TimeSpan structure allows you to easily define and transform units of time using various members.

DateTime dt = new DateTime(2015, 10, 17); // (year, month, day) 
Console.WriteLine("Day {0} {1}", dt.Date, dt.DayOfWeek);
dt = dt.AddMonths(2);
TimeSpan ts = new TimeSpan(4, 30, 0); // (hours, minutes, seconds) 
Console.WriteLine(ts);

The DateOnly and TimeOnly structs were added in .NET 6/C# 10 , and each represents half of the DateTime type. The DateOnly struct aligns with the SQL Server Date type, and the TimeOnly struct aligns with the SQL Server Time Type.

DateOnly d = new DateOnly(2021, 07, 21);
TimeOnly t = new TimeOnly(13, 30, 0, 0);

Working with the System.Numerics Namespace

The System.Numerics namespace defines a structure named "BigInteger". The BigInteger data type can be used when you need to represent humongous numerical values, which are not constrained by a fixed upper or lower limit.

Also System.Numerics namespace defines "Complex", which allows you to model mathematically complex numerical data.

using System.Numerics; 

Note : After you assign a value to a BigInteger, you cannot change it, as the data is immutable.

BigInteger big = new BigInteger("999"); 

Properties

IsEvenThe big integer is an even or not number.
IsPowerOfTwoIndicates whether the value of the current BigInteger object is a power of 2.

Using Digit Separators (New 7.0)

C# 7.0 introduced the underscore (_) as a digit separator (for integer, long, decimal, double, or hex types.)

Console.WriteLine(123_456);
Console.WriteLine(123_456_12F);
Console.WriteLine(123_456.12M);
Console.WriteLine(0x_00_00F);

Using Binary Literals

Starts -> 0b_

Console.WriteLine("16 : {0}", 0b_0001_0000);
Console.WriteLine("32 : {0}", 0b_0010_0000);