Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

C# Dictionary

  1. Home
  2. C# Dictionary
  3. Basic Data Types (C#)

Basic Data Types (C#)

An overview of the basic data types (primitive types) in C#, including the difference between value types and reference types, type inference with var, and implicit/explicit type conversion. Choosing the right type helps improve memory efficiency and prevent bugs.

Basic Data Types

Type nameAliasSizeRange / Description
System.Int32int32-bit-2,147,483,648 to 2,147,483,647. The most commonly used integer type.
System.Int64long64-bit-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. Use when the value does not fit in int.
System.Doubledouble64-bitApproximately ±1.7×10³⁰⁸. Double-precision floating-point. The default type for floating-point literals.
System.Singlefloat32-bitApproximately ±3.4×10³⁸. Single-precision floating-point. Widely used in Unity and similar environments. Literals require the f suffix.
System.Decimaldecimal128-bit28–29 significant decimal digits. Use where rounding errors are unacceptable, such as financial calculations. Literals require the m suffix.
System.Charchar16-bitA single Unicode character (U+0000 to U+FFFF). Enclosed in single quotes.
System.Booleanbool1-bit equivalenttrue or false only. The only type that can be used directly in a condition expression.
System.StringstringVariable lengthA Unicode string. A reference type, but immutable — it can be used intuitively like a value type.

Value Types vs. Reference Types

Value TypeReference Type
Storage locationStack (or inside a struct field).Heap (the variable holds a reference to the heap object).
Assignment behaviorThe value itself is copied.The reference (address) is copied.
Default value0 / false / '\0', etc., depending on the type.null (no reference).
Representative typesint / long / double / float / decimal / char / bool / structstring / arrays / classes / object

string is classified as a reference type, but strings are immutable, so assigning a different string to a variable does not affect the original string object. This is why string can be used intuitively, much like a value type.

Type Inference with var

When you use var, the compiler automatically infers the type from the right-hand side expression at compile time. The type is still statically determined — it does not change at runtime. Using var can improve readability when the type name would be long, but when the type is not obvious from the right-hand side, an explicit type name is clearer.

var power = 9000; // Inferred as int.
var name = "Son Goku"; // Inferred as string.
var ratio = 1.5; // Inferred as double.
var isAlive = true; // Inferred as bool.

// When the type is not obvious from the right-hand side, use an explicit type name.
int hp = 0;
string title = "Super Saiyan";

Sample Code

BasicTypes.cs

A sample that declares and prints each basic type.

using System;

class BasicTypes {
	static void Main() {

		int power = 9000; // Power level (fits within int range).
		int maxPower = int.MaxValue; // Check the maximum value of int.
		Console.WriteLine("power = " + power);
		Console.WriteLine("int.Max = " + maxPower); // Outputs 2147483647.

		// Expressed with a long literal (append the L suffix).
		long frieza = 530_000_000L; // Underscores improve readability of large numbers.
		Console.WriteLine("Frieza power = " + frieza);

		double multiplier = 1.5; // Super Saiyan multiplier (assumed value).
		double result = power * multiplier;
		Console.WriteLine("Super Saiyan power = " + result); // Outputs 13500.

		float speed = 9.8f; // Movement speed (float).
		Console.WriteLine("speed = " + speed);

		// Use where rounding errors are unacceptable, such as monetary calculations.
		decimal price = 1980.50m; // Item price (before tax).
		decimal taxRate = 0.10m;
		decimal taxPrice = price * (1 + taxRate); // Calculate price including tax.
		Console.WriteLine("Price with tax = " + taxPrice); // Outputs 2178.5500.

		char initial = 'G'; // First letter of the name.
		Console.WriteLine("initial = " + initial);
		Console.WriteLine("charCode = " + (int)initial); // Check the Unicode code point.

		bool isSaiyan = true;
		bool hasTail = false;
		Console.WriteLine("Saiyan: " + isSaiyan + ", Has tail: " + hasTail);

		string hero = "Son Goku";
		string transformed = hero + " (Super Saiyan)"; // Concatenation creates a new string object.
		Console.WriteLine(transformed); // The original hero variable is unchanged.
		Console.WriteLine("hero = " + hero); // Still "Son Goku".
	}
}

Run the following command:

dotnet script BasicTypes.cs
power = 9000
int.Max = 2147483647
Frieza power = 530000000
Super Saiyan power = 13500
speed = 9.8
Price with tax = 2178.5500
initial = G
charCode = 71
Saiyan: True, Has tail: False
Son Goku (Super Saiyan)
hero = Son Goku
TypeConversion.cs

A sample demonstrating implicit conversion, explicit casts, and the Convert class.

using System;

class TypeConversion {
	static void Main() {

		// Converting from a smaller type to a larger type happens automatically (no data loss).

		int intPower = 9000;
		long longPower = intPower; // int → long: converted implicitly.
		float floatPower = intPower; // int → float: converted implicitly.
		double doublePower = intPower; // int → double: converted implicitly.

		Console.WriteLine("=== Implicit conversion ===");
		Console.WriteLine("int → long: " + longPower);
		Console.WriteLine("int → float: " + floatPower);
		Console.WriteLine("int → double: " + doublePower);

		// Main implicit conversion directions: int → long → float → double
		// int → float has about 7 significant digits, so large values may lose precision.
		int bigInt = 123456789;
		float bigFloat = bigInt; // Precision may be reduced.
		Console.WriteLine("\nbigInt = " + bigInt);
		Console.WriteLine("→ float = " + bigFloat); // Rounded to something like 123456790.

		// Converting from a larger type to a smaller type, or when precision is lost,
		// requires the cast operator (type name).

		Console.WriteLine("\n=== Explicit cast ===");

		double vegeta = 8500.9;
		int castedPower = (int)vegeta; // double → int: the fractional part is truncated.
		Console.WriteLine("double: " + vegeta + " → int: " + castedPower); // Becomes 8500.

		long frieza = 530_000_000L;
		int castedFrieza = (int)frieza; // long → int: be careful the value fits in int range.
		Console.WriteLine("long: " + frieza + " → int: " + castedFrieza);

		// Casting a value that exceeds int.MaxValue causes overflow (no exception by default).
		long overflowVal = 3_000_000_000L; // Exceeds int's maximum (~2.1 billion).
		int overflowed = (int)overflowVal;
		Console.WriteLine("Overflow example: long " + overflowVal + " → int " + overflowed);

		// char and int can be cast to each other.
		char initial = 'G';
		int code = (int)initial;
		char restored = (char)code;
		Console.WriteLine("\n'G' → int: " + code + " → char: '" + restored + "'");

		// Unlike a cast, the Convert class throws an exception on overflow.
		// It also handles string ↔ numeric conversions.
		Console.WriteLine("\n=== Convert class ===");

		string powerStr = "9000";
		int parsed = Convert.ToInt32(powerStr); // string → int.
		string backStr = Convert.ToString(parsed); // int → string.
		Console.WriteLine("string → int: " + parsed);
		Console.WriteLine("int → string: " + backStr);

		double piVal = 3.14159;
		int piInt = Convert.ToInt32(piVal); // double → int (rounded).
		Console.WriteLine("double " + piVal + " → int (rounded): " + piInt);
	}
}

The following example demonstrates this:

dotnet script TypeConversion.cs
=== Implicit conversion ===
int → long: 9000
int → float: 9000
int → double: 9000

bigInt = 123456789
→ float = 123456790

=== Explicit cast ===
double: 8500.9 → int: 8500
long: 530000000 → int: 530000000
Overflow example: long 3000000000 → int -1294967296

'G' → int: 71 → char: 'G'

=== Convert class ===
string → int: 9000
int → string: 9000
double 3.14159 → int (rounded): 3

Common Mistakes

Assigning a literal to decimal without the m suffix

When assigning a numeric literal to a decimal variable, forgetting the m suffix causes a compile error. Numeric literals default to double, and implicit conversion from double to decimal is not allowed.

decimal price = 1980.50; // Error: cannot implicitly convert type 'double' to 'decimal'.

decimal price = 1980.50m;

Similarly, float requires the f suffix.

float speed = 9.8; // Error: cannot implicitly convert type 'double' to 'float'.

float speed = 9.8f;

Precision errors with float / double arithmetic

float and double store values in binary, so some decimal values cannot be represented exactly. Using double for monetary calculations can produce unexpected results.

double a = 0.1 + 0.2;
Console.WriteLine(a == 0.3); // False (the result is 0.30000000000000004)

// Use decimal for monetary calculations.
decimal b = 0.1m + 0.2m;
Console.WriteLine(b == 0.3m); // True

Summary

Among C#'s basic data types, int / long / double / float / decimal / char / bool are value types (the value itself is stored on the stack), while string is a reference type (the actual data is stored on the heap). string is a reference type, but because it is immutable, "modifying" a string internally creates a new string object. The original string assigned to a variable does not change, so you can work with strings as safely as with value types.

For floating-point numbers, use double (the default) or float (commonly used in Unity) depending on your needs. For financial calculations or any situation where rounding errors are unacceptable, always use decimal. Because float and double store values in binary, expressions like 0.1 + 0.2 can produce results such as 0.30000000000000004.

For type conversion, converting from a smaller type to a larger type (e.g., intlong) is done implicitly, but converting from a larger type to a smaller type (e.g., doubleint) requires an explicit cast operator (type name). Casting a value that exceeds the int range causes overflow and produces an unexpected result. When you need a safe conversion, use the Convert class (which throws an exception on overflow) or a checked block. For conversions between string and numeric types, see also Convert.ToInt32(), int.Parse(), and int.TryParse().

If you find any errors or copyright issues, please .