Other answers offer good help with this question, but there is an important and subtle issue that none of them addresses directly. There are two ways of considering type in C#: static type and run-time type.
Static type is the type of a variable in your source code. It is therefore a compile-time concept. This is the type that you see in a tooltip when you hover over a variable or property in your development environment.
Run-time type is the type of an object in memory. It is therefore a run-time concept. This is the type returned by the GetType() method.
An object's run-time type is frequently different from the static type of the variable, property, or method that holds or returns it. For example, you can have code like this:
object o = "Some string";
The static type of the variable is object, but at run time, the type of the variable's referent is string. Therefore, the next line will print "System.String" to the console:
Console.WriteLine(o.GetType()); // prints System.String
But, if you hover over the variable o in your development environment, you'll see the type System.Object (or the equivalent object keyword).
For value-type variables, such as int, double, System.Guid, you know that the run-time type will always be the same as the static type, because value types cannot serve as the base class for another type; the value type is guaranteed to be the most-derived type in its inheritance chain. This is also true for sealed reference types: if the static type is a sealed reference type, the run-time value must either be an instance of that type or null.
Conversely, if the static type of the variable is an abstract type, then it is guaranteed that the static type and the runtime
Uaw GetType() method
Example
int n = 34;
Console.WriteLine(n.GetType());
string name = "Smome";
Console.WriteLine(name.GetType());