Skip to main content

C# Types and variables (C# Specification Part 2)

There are two kinds of types in C#: value types and reference types. Variables of value types directly contain their data whereas variables of reference types store references to their data, the latter being known as objects. With reference types, it is possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other (except in the case of ref and out parameter variables).

C#’s value types are further divided into simple types, enum types, struct types, and nullable types, and C#’s reference types are further divided into class types, interface types, array types, and delegate types.

The following table provides an overview of C#’s type system.

Category
Description
Value
types
Simple types
Signed integral: sbyte, short, int, long
Unsigned integral: byte, ushort, uint, ulong
Unicode characters: char
IEEE floating point: float, double
High-precision decimal: decimal
Boolean: bool
Enum types
User-defined types of the form enum E {...}
Struct types
User-defined types of the form struct S {...}
Nullable types
Extensions of all other value types with a null value
Reference
types
Class types
Ultimate base class of all other types: object
Unicode strings: string
User-defined types of the form class C {...}
Interface types
User-defined types of the form interface I {...}
Array types
Single- and multi-dimensional, for example, int[] and int[,]
Delegate types
User-defined types of the form e.g. delegate int D(...)

The eight integral types provide support for 8-bit, 16-bit, 32-bit, and 64-bit values in signed or unsigned form.

The two floating point types, float and double, are represented using the 32-bit single-precision and 64-bit double-precision IEEE 754 formats.

The decimal type is a 128-bit data type suitable for financial and monetary calculations.
C#’s bool type is used to represent boolean values—values that are either true or false.
Character and string processing in C# uses Unicode encoding. The char type represents a UTF-16 code unit, and the string type represents a sequence of UTF-16 code units.
The following table summarizes C#’s numeric types.

Category
Bits
Type
Range/Precision
Signed integral
8
sbyte
–128...127
16
short
–32,768...32,767
32
int
–2,147,483,648...2,147,483,647
64
long
–9,223,372,036,854,775,808...9,223,372,036,854,775,807
Unsigned integral
8
byte
0...255
16
ushort
0...65,535
32
uint
0...4,294,967,295
64
ulong
0...18,446,744,073,709,551,615
Floating point
32
float
1.5 × 10−45 to 3.4 × 1038, 7-digit precision
64
double
5.0 × 10−324 to 1.7 × 10308, 15-digit precision
Decimal
128
decimal
1.0 × 10−28 to 7.9 × 1028, 28-digit precision

C# programs use type declarations to create new types. A type declaration specifies the name and the members of the new type. Five of C#’s categories of types are user-definable: class types, struct types, interface types, enum types, and delegate types.
A class type defines a data structure that contains data members (fields) and function members (methods, properties, and others). Class types support single inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes.

A struct type is similar to a class type in that it represents a structure with data members and function members. However, unlike classes, structs are value types and do not require heap allocation. Struct types do not support user-specified inheritance, and all struct types implicitly inherit from type object.

An interface type defines a contract as a named set of public function members. A class or struct that implements an interface must provide implementations of the interface’s function members. An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

A delegate type represents references to methods with a particular parameter list and return type. Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegates are similar to the concept of function pointers found in some other languages, but unlike function pointers, delegates are object-oriented and type-safe.

Class, struct, interface and delegate types all support generics, whereby they can be parameterized with other types.

An enum type is a distinct type with named constants. Every enum type has an underlying type, which must be one of the eight integral types. The set of values of an enum type is the same as the set of values of the underlying type.

C# supports single- and multi-dimensional arrays of any type. Unlike the types listed above, array types do not have to be declared before they can be used. Instead, array types are constructed by following a type name with square brackets. For example, int[] is a single-dimensional array of int, int[,] is a two-dimensional array of int, and int[][] is a single-dimensional array of single-dimensional arrays of int.

Nullable types also do not have to be declared before they can be used. For each non-nullable value type T there is a corresponding nullable type T?, which can hold an additional value null. For instance, int? is a type that can hold any 32 bit integer or the value null.

C#’s type system is unified such that a value of any type can be treated as an object. Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. Values of reference types are treated as objects simply by viewing the values as type object. Values of value types are treated as objects by performing boxing and unboxing operations. In the following example, an int value is converted to object and back again to int.

using System;
class Test
{
      static void Main() {
            int i = 123;
            object o = i;                 // Boxing
            int j = (int)o;         // Unboxing
      }
}

When a value of a value type is converted to type object, an object instance, also called a “box,” is allocated to hold the value, and the value is copied into that box. Conversely, when an object reference is cast to a value type, a check is made that the referenced object is a box of the correct value type, and, if the check succeeds, the value in the box is copied out.
C#’s unified type system effectively means that value types can become objects “on demand.” Because of the unification, general-purpose libraries that use type object can be used with both reference types and value types.

There are several kinds of variables in C#, including fields, array elements, local variables, and parameters. Variables represent storage locations, and every variable has a type that determines what values can be stored in the variable, as shown by the following table.

Type of Variable
Possible Contents
Non-nullable value type
A value of that exact type
Nullable value type
A null value or a value of that exact type
object
A null reference, a reference to an object of any reference type, or a reference to a boxed value of any value type
Class type
A null reference, a reference to an instance of that class type, or a reference to an instance of a class derived from that class type
Interface type
A null reference, a reference to an instance of a class type that implements that interface type, or a reference to a boxed value of a value type that implements that interface type
Array type
A null reference, a reference to an instance of that array type, or a reference to an instance of a compatible array type
Delegate type
A null reference or a reference to an instance of that delegate type

Comments

Popular posts from this blog

Accessing File Stored in Windows Azure Blob Storage Using jQuery

Did you know it was possible to access the Windows Azure Blob Storage directly from JavaScript, for example using jQuery? At first, it sounds obvious, since Blobs are after all accessible from a public UR. But in practice, there is a very big hurdle: the Web browser’s Same Origine Policy or SOP, that restricts JavaScript code to accessing resources originating from the same site the script was loaded from. This means that you will never be able to load a Windows Azure Blob using XMLHttpRequest for example! Fortunately, there is a popular workaround called JSONP (“JSON with Padding”). The idea behind this technique is that the script tag is not submitted to the SOP: an HTML page can thus load a JavaScript file from any site. So, if you expose your data in an “executable” form in JavaScript, a page will be able to load this data using a script tag. For example: <script type=”text/javascript” src=”http://www.sandeepknarware.in/exemple.jsonp”> </script> But how can ...

Support for debugging lambda expressions with Visual Studio 2015

Anyone who uses LINQ (or lambdas in general) and the debugger will quickly discover the dreaded message “Expression cannot contain lambda expressions”. Lack of lambda support has been a limitation of the Visual Studio Debugger ever since Lambdas were added to C# and Visual Basic.  With visual studio 2015 Microsoft has added support for debugging lambda expressions. Let’s first look at an example, and then I’ll walk you through current limitations. Example To try this yourself, create a new C# Console app with this code: using System.Diagnostics; using System.Linq; class Program { static void Main() { float[] values = Enumerable.Range(0, 100).Select(i => (float)i / 10).ToArray(); Debugger.Break(); } } Then compile, start debugging, and add “values.Where(v => (int)v == 3).ToArray()” in the Watch window. You’ll be happy to see the same as what the screenshot above shows you. I am using Visual Studio 2015 Preview and it has some limitati...

gcAllowVeryLargeObjects Element

There are numerous new features coming with .NET 4.5 and here, on this blog, you can find several posts about it. But the feature we are goint to talk about today is very exciting, because we were waiting for it more than 10 years. Since .NET 1.0 the memory limit of .NET object is 2GB. This means you cannot for example create array which contains elements with more than 2GB in total. If try to create such array, you will get the OutOfMemoryException. Let’s see an example how to produce OutOfMemoryException. Before that Open Visual Studio 2012, and create C# Console Application, like picture below. First lets create simple struct with two double members like example below: 1 2 3 4 5 6 7 8 9 10 11 12 public struct ComplexNumber {      public double Re;      public double Im;      public ComplexNumber( double re, double im)      {    ...