Types
C# is a strongly typed language; therefore every variable and object must have a declared type.
Data Types Overview
A type can be described as being either:
A built-in numeric type, such as an int or char, or
A user-defined type, such as a class or interface.
An anonymous type, which consists of a set of public properties encapsulated in a nameless reference type.
Types can also be defined as being either:
Value Types (C# Reference), which store values. These include the primitive numeric types, enums and structs, and also nullable versions of these types.
Reference Types (C# Reference), which store references to the actual data. These include classes, interfaces, arrays and delegates.
Типы
C# — это строго типизированный язык, поэтому каждая переменная и каждый объект должны иметь объявленный тип.
Общие сведения о типах данных
Тип можно описать как:
Встроенный числовой тип, например int или char, или
Пользовательский тип, например class или interface.
Анонимный тип, состоящий из набора общих свойств, инкапсулированных в безымянном ссылочном типе.
Типы также могут быть заданы как:
Типы значений, то есть хранящие значения. К ним относятся простые числовые типы, перечисления и структуры, а также версии этих типов, допускающие значения NULL.
Ссылочные типы, то есть хранящие ссылки на фактические данные. К ним относятся классы, интерфейсы, массивы и делегаты.
Casting
Converting between data types can be done explicitly by using a cast, but in some cases, implicit conversions are allowed. For example:
static void TestCasting()
{
int i = 10;
float f = 0;
f = i; // An implicit conversion, no data will be lost.
f = 0.5F;
i = (int)f; // An explicit conversion. Information will be lost.
}
|
A cast explicitly invokes the conversion operator from one type to another. The cast fail if no such conversion operator is defined. A cast operation between reference types does not change the type of the underlying object; it only changes the type of the variable that is being used as a reference to that object.
You can write custom conversion operators to convert between user-defined types.
Example
The following program casts a double to an int. The program will not compile without the cast.
class Test
{
static void Main()
{
double x = 1234.7;
int a;
a = (int)x; // cast double to int
System.Console.WriteLine(a);
}
}
|
Output
1234
Приведение
Преобразование между типами данных может быть выполнено явно с помощью приведения, но в некоторых случаях разрешены неявные преобразования. Пример.
static void TestCasting()
{
int i = 10;
float f = 0;
f = i; // An implicit conversion, no data will be lost.
f = 0.5F;
i = (int)f; // An explicit conversion. Information will be lost.
}
|
Приведение явно вызывает оператор преобразования из одного типа в другой. Если ни один такой оператор не определен, приведение завершается неудачей. Операция приведения между ссылочными типами не меняет тип объекта; меняется только тип переменной, которая используется в качестве ссылки на этот объект. Для преобразований между пользовательскими типами можно создавать специальные операторы преобразования.
Пример
Следующая программа выполнят приведение типа double к типу int. Без приведения эта программа скомпилирована не будет.
class Test
{
static void Main()
{
double x = 1234.7;
int a;
a = (int)x; // cast double to int
System.Console.WriteLine(a);
}
}
|
Результат
1234
Boxing and Unboxing
Boxing and unboxing enable value types to be treated as objects. Boxing a value type packages it inside an instance of the Object reference type. This allows the value type to be stored on the garbage collected heap. Unboxing extracts the value type from the object. In this example, the integer variable i is boxed and assigned to object o.
int i = 123;
object o = (object)i; // boxing
|
The object o can then be unboxed and assigned to integer variable i:
o = 123;
i = (int)o; // unboxing
|
Performance
In relation to simple assignments, boxing and unboxing are computationally expensive processes. When a value type is boxed, a new object must be allocated and constructed. To a lesser degree, the cast required for unboxing is also expensive computationally.
Упаковка-преобразование и распаковка-преобразование3
Операции упаковки-преобразования и распаковки-преобразования позволяют обрабатывать типы значения в качестве объектов. Упаковка-преобразование пакетов типа значения выполняется внутри экземпляра ссылочного типа Object. Это позволяет хранить этот тип значения в куче, в которой производится сборка мусора. Операция распаковки-преобразования извлекает тип значения из объекта. В приведенном примере выполнена операция упаковки-преобразования целочисленной переменой i, которая назначена объекту o.
int i = 123;
object o = (object)i; // boxing
|
Можно затем выполнить операцию распаковки-преобразования объекта o и назначить его целочисленной переменной i:
o = 123;
i = (int)o; // unboxing
|
Производительность
По сравнению с простыми операциями присваивания операции упаковки-преобразования и распаковки-преобразования являются весьма затратными процессами с точки зрения вычислений. При выполнении упаковки-преобразования типа значения необходимо создать и разместить новый объект. Объем вычислений при выполнении операции распаковки-преобразования, хотя и в меньшей степени, но тоже весьма значителен.
Boxing Conversion
Boxing is used to store value types in the garbage-collected heap. Boxing is an implicit conversion of a value type to the type object or to any interface type implemented by this value type. Boxing a value type allocates an object instance on the heap and copies the value into the new object.
Consider the following declaration of a value-type variable:
The following statement implicitly applies the boxing operation on the variable i:
object o = i; // implicit boxing
|
The result of this statement is creating an object reference o, on the stack, that references a value of the type int, on the heap. This value is a copy of the value-type value assigned to the variable i. The difference between the two variables, i and o, is illustrated in the following figure.
Boxing Conversion
It also possible to perform the boxing explicitly as in the following example, but explicit boxing is never required:
int i = 123;
object o = (object)i; // explicit boxing
|
Упаковка-преобразование4
Упаковка используется для хранения типов значений в куче "сбора мусора". Упаковка представляет собой неявное преобразование типа значения в тип object или любой другой тип интерфейса, реализуемый этим типом значения. При упаковке типа значения в куче выделяется экземпляр объекта и выполняется копирование значения в этот новый объект.
Рассмотрим следующее объявление переменной типа значения.
Следующий оператор неявно применяет операцию упаковки к переменной i.
object o = i; // implicit boxing
|
Результат этого оператора создает ссылку на объект o в стеке, которая ссылается на значение типа int в куче. Это значение является копией значения типа значения, назначенного переменной i. Разница между двумя этими переменными, i и o, продемонстрирована на рисунке ниже.
Упаковка-преобразование
Можно также выполнять упаковку явным способом, как в следующем примере, однако явная упаковка не является обязательной.
int i = 123;
object o = (object)i; // explicit boxing
|
Description
This example converts an integer variable i to an object o by using boxing. Then, the value stored in the variable i is changed from 123 to 456. The example shows that the original value type and the boxed object use separate memory locations, and therefore can store different values.
Example
class TestBoxing
{
static void Main()
{
int i = 123;
object o = i; // implicit boxing
i = 456; // change the contents of i
System.Console.WriteLine("The value-type value = {0}", i);
System.Console.WriteLine("The object-type value = {0}", o);
}
}
|
Output
The value-type value = 456
The object-type value = 123
Описание5
Этот пример преобразует целочисленную переменную i в объект o при помощи упаковки. Затем значение, хранимое переменной i, меняется с 123 на 456. В примере показано, что исходный тип значения и упакованный объект используют отдельные ячейки памяти, а значит, могут хранить разные значения.
Пример
class TestBoxing
{
static void Main()
{
int i = 123;
object o = i; // implicit boxing
i = 456; // change the contents of i
System.Console.WriteLine("The value-type value = {0}", i);
System.Console.WriteLine("The object-type value = {0}", o);
}
}
|
Результат
The value-type value = 456
The object-type value = 123
Unboxing Conversion
Unboxing is an explicit conversion from the type object to a value type or from an interface type to a value type that implements the interface. An unboxing operation consists of:
Checking the object instance to make sure that it is a boxed value of the given value type.
Copying the value from the instance into the value-type variable.
The following statements demonstrate both boxing and unboxing operations:
int i = 123; // a value type
object o = i; // boxing
int j = (int)o; // unboxing
|
The following figure demonstrates the result of the previous statements.
Unboxing Conversion
For the unboxing of value types to succeed at run time, the item being unboxed must be a reference to an object that was previously created by boxing an instance of that value type. Attempting to unbox null or a reference to an incompatible value type will cause an InvalidCastException.
Распаковка-преобразование6
Распаковка является явным преобразованием из типа object в тип значения или из типа интерфейса в тип значения, его реализующее. Операция распаковки состоит из следующих действий.
Проверка экземпляра объекта на то, что он является упакованным значением заданного типа значения.
Копирование значения из экземпляра в переменную типа-значения.
В следующих операторах показаны операции по упаковке и распаковке.
int i = 123; // a value type
object o = i; // boxing
int j = (int)o; // unboxing
|
На следующем рисунке представлен результат выполнения предыдущих операторов.
Распаковка-преобразование
Для успешной распаковки типов значений во время выполнения необходимо, чтобы экземпляр, который распаковывается, был ссылкой на объект, предварительно созданный с помощью упаковки экземпляра этого типа значения. Попытка распаковать null или ссылку в несовместимый тип значения вызовет InvalidCastException.
Description
The following example demonstrates a case of invalid unboxing and the resulting InvalidCastException. Using try and catch, an error message is displayed when the error occurs.
Example
class TestUnboxing
{
static void Main()
{
int i = 123;
object o = i; // implicit boxing
try
{
int j = (short)o; // attempt to unbox
System.Console.WriteLine("Unboxing OK.");
}
catch (System.InvalidCastException e)
{
System.Console.WriteLine("{0} Error: Incorrect unboxing.", e.Message);
}
}
}
|
Output
Specified cast is not valid. Error: Incorrect unboxing.
If you change the statement:
to:
the conversion will be performed, and you will get the output:
Unboxing OK.
Описание7
В следующем примере показан случай недопустимого процесса распаковки, в результате которого вызывается InvalidCastException. При использовании try и catch, когда возникает ошибка, выводится сообщение об ошибке.
Пример
class TestUnboxing
{
static void Main()
{
int i = 123;
object o = i; // implicit boxing
try
{
int j = (short)o; // attempt to unbox
System.Console.WriteLine("Unboxing OK.");
}
catch (System.InvalidCastException e)
{
System.Console.WriteLine("{0} Error: Incorrect unboxing.", e.Message);
}
}
}
|
Результат
Specified cast is not valid. Error: Incorrect unboxing.
При изменении оператора
на
будет выполнено преобразование со следующим результатом.
Unboxing OK.
How to: Convert a byte Array to an int
This example shows you how to use the BitConverter class to convert an array of bytes to an int and back to an array of bytes. You may have to convert from bytes to a built-in data type after you read bytes off the network, for example. In addition to the ToInt32(array[]()[], Int32) method in the example, the following table lists methods in the BitConverter class that convert bytes (from an array of bytes) to other built-in types.
Type returned
|
Method
|
bool
|
ToBoolean(array[]()[], Int32)
|
char
|
ToChar(array[]()[], Int32)
|
double
|
ToDouble(array[]()[], Int32)
|
short
|
ToInt16(array[]()[], Int32)
|
int
|
ToInt32(array[]()[], Int32)
|
long
|
ToInt64(array[]()[], Int32)
|
float
|
ToSingle(array[]()[], Int32)
|
ushort
|
ToUInt16(array[]()[], Int32)
|
uint
|
ToUInt32(array[]()[], Int32)
|
ulong
|
ToUInt64(array[]()[], Int32)
|
Преобразование массива байтов в значение типа "int"8
В этом примере демонстрируется использование класса BitConverter для преобразования массива байтов в значение типа int и обратно в массив байтов. Например, может потребоваться преобразование из байтов во встроенный тип данных после чтения байтов из сети. В дополнение к методу ToInt32(array[]()[], Int32), показанному в примере, для преобразования байтов (из массива байтов) в другие встроенные типы данных могут использоваться и другие методы класса BitConverter, представленные в следующей таблице.
--
Example
This example initializes an array of bytes, reverses the array if the computer architecture is little-endian (that is, the least significant byte is stored first), and then calls the ToInt32(array[]()[], Int32) method to convert four bytes in the array to an int. The second argument to ToInt32(array[]()[], Int32) specifies the start index of the array of bytes.
Note:
|
The output may differ depending on the endianess of your computer's architecture.
|
byte[] bytes = { 0, 0, 0, 25 };
// If the system architecture is little-endian (that is, little end first),
// reverse the byte array.
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
int i = BitConverter.ToInt32(bytes, 0);
Console.WriteLine("int: {0}", i);
|
In this example, the GetBytes(Int32) method of the BitConverter class is called to convert an int to an array of bytes.
Note:
|
The output may differ depending on the endianess of your computer's architecture.
|
byte[] bytes = BitConverter.GetBytes(201805978);
Console.WriteLine("byte array: " + BitConverter.ToString(bytes));
|
Пример9
Этот пример инициализирует массив байтов, обращает порядок расположения элементов в массиве, если в архитектуре компьютера используется прямой порядок байтов (т. е. первым сохраняется наименее значащий байт), и затем вызывает метод ToInt32(array[]()[], Int32) для преобразования четырех байтов массива в значение типа int. Второй аргумент ToInt32(array[]()[], Int32) указывает начальный индекс массива байтов.
Примечание.
|
Результат может отличаться в зависимости от порядка следования байтов в архитектуре компьютера.
|
byte[] bytes = { 0, 0, 0, 25 };
// If the system architecture is little-endian (that is, little end first),
// reverse the byte array.
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
int i = BitConverter.ToInt32(bytes, 0);
Console.WriteLine("int: {0}", i);
|
В этом примере метод GetBytes(Int32) класса BitConverter вызывается для преобразования значения типа int в массив байтов.
Примечание.
|
Результат может отличаться в зависимости от порядка следования байтов в архитектуре компьютера.
|
byte[] bytes = BitConverter.GetBytes(201805978);
Console.WriteLine("byte array: " + BitConverter.ToString(bytes));
|
How to: Convert a string to an int
These examples show some different ways you can convert a string to an int. Such a conversion can be useful when obtaining numerical input from a command line argument, for example. Similar methods exist for converting strings to other numeric types, such as float or long. The table below lists some of those methods.
Numeric Type
|
Method
|
decimal
|
ToDecimal(String)
|
float
|
ToSingle(String)
|
double
|
ToDouble(String)
|
short
|
ToInt16(String)
|
long
|
ToInt64(String)
|
ushort
|
ToUInt16(String)
|
uint
|
ToUInt32(String)
|
ulong
|
ToUInt64(String)
|
Example
This example calls the ToInt32(String) method to convert the string "29" to an int. It then adds 1 to the result and prints the output.
int i = Convert.ToInt32("29");
i++;
Console.WriteLine(i);
|
30
|
Преобразование строки в значение типа "int"
В следующих примерах показано как преобразовать строку в значение типа int. Такое преобразование можно использовать, к примеру, при получении числовых входных данных из аргументов командной строки. Существуют аналогичные методы преобразования строк в другие числовые типы, такие как float и long. В следующей таблице перечислены некоторые из этих методов класса Convert.
--
Пример
В данном примере вызывается метод ToInt32(String) класса Convert для преобразования строки "29" в значение типа int. Затем к результату добавляется 1, а выходные данные печатаются.
int i = Convert.ToInt32("29");
i++;
Console.WriteLine(i);
|
30
|
Another way of converting a string to an int is through the Parse or TryParse methods of the System..::.Int32 struct. The ToUInt32 method uses Parse internally. If the string is not in a valid format, Parse throws an exception whereas TryParse does not throw an exception but returns false. The examples below demonstrate both successful and unsuccessful calls to Parse and TryParse.
int i = Int32.Parse("-105");
Console.WriteLine(i);
|
-105
|
int j;
Int32.TryParse("-105", out j);
Console.WriteLine(j);
|
-105
|
try
{
int m = Int32.Parse("abc");
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
|
Input string was not in a correct format.
|
string s = "abc";
int k;
bool parsed = Int32.TryParse(s, out k);
if (!parsed)
Console.WriteLine("Int32.TryParse could not parse '{0}' to an int.\n", s);
|
Int32.TryParse could not parse 'abc' to an int.
|
Также можно преобразовать значение типа string в значение типа int с помощью методов Parse или TryParse структуры System..::.Int32. Метод ToUInt32 использует Parse внутри себя. Если строка имеет недопустимый формат, метод Parse создает исключение, а метод TryParse не создает исключение, но возвращает значение "false". В приведенных ниже примерах демонстрируются успешные и неуспешные вызовы методов Parse и TryParse.
--
How to: Convert Hexadecimal Strings
These examples show you how to convert to and from hexadecimal strings. The first example shows you how to obtain the hexadecimal value of each character in a string. The second example parses a string of hexadecimal values and outputs the character corresponding to each hexadecimal value. The third example demonstrates an alternative way to parse a hexadecimal string value to an integer.
Example
This example outputs the hexadecimal value of each character in a string. First it parses the string to an array of characters. Then it calls ToInt32(Char) on each character to obtain its numeric value. Finally, it formats the number as its hexadecimal representation in a string.
string input = "Hello World!";
char[] values = input.ToCharArray();
foreach (char c in values)
{
// Get the integral value of the character.
int value = Convert.ToInt32(c);
// Convert the decimal value to a hexadecimal value in string form.
string hex = String.Format("{0:X}", value);
Console.WriteLine("Hexadecimal value of {0} is {1}", c, hex);
}
|
Hexadecimal value of H is 48
Hexadecimal value of e is 65
Hexadecimal value of l is 6C
Hexadecimal value of l is 6C
Hexadecimal value of o is 6F
Hexadecimal value of is 20
Hexadecimal value of W is 57
Hexadecimal value of o is 6F
Hexadecimal value of r is 72
Hexadecimal value of l is 6C
Hexadecimal value of d is 64
Hexadecimal value of ! is 21
|
Преобразование шестнадцатеричных строк10
В следующих примерах показано, как выполнить преобразование в шестнадцатеричные строки и наоборот. Первый пример демонстрирует, как получить шестнадцатеричное значение каждого символа в строке. Второй пример выполняет разбор строки шестнадцатеричных значений и выводит символ, соответствующий каждому шестнадцатеричному значению. Третий пример демонстрирует альтернативный способ разбора значения шестнадцатеричной строки до целого числа.
Пример
Результатом следующего примера является шестнадцатеричное значение каждого символа в string. Сначала выполняется разбор string до массива символов. Затем для каждого символа вызывается метод ToInt32(Char) для получения его числового значения. В конце, число представляется шестнадцатеричном виде.
--
This example parses a string of hexadecimal values and outputs the character corresponding to each hexadecimal value. First it calls the Split(array[]()[]) method to obtain each hexadecimal value as an individual string in an array. Then it calls ToInt32(String, Int32) to convert the hexadecimal value to a decimal value represented as an int. It shows two different ways to obtain the character corresponding to that character code. The first technique uses ConvertFromUtf32(Int32) which returns the character corresponding to the integer argument as a string. The second technique explicitly casts the int to a char.
string hexValues = "48 65 6C 6C 6F 20 57 6F 72 6C 64 21";
string[] hexValuesSplit = hexValues.Split(' ');
foreach (String hex in hexValuesSplit)
{
// Convert the number expressed in base-16 to an integer.
int value = Convert.ToInt32(hex, 16);
// Get the character corresponding to the integral value.
string stringValue = Char.ConvertFromUtf32(value);
char charValue = (char)value;
Console.WriteLine("hexadecimal value = {0}, int value = {1}, char value = {2} or {3}", hex, value, stringValue, charValue);
}
|
hexadecimal value = 48, int value = 72, char value = H or H
hexadecimal value = 65, int value = 101, char value = e or e
hexadecimal value = 6C, int value = 108, char value = l or l
hexadecimal value = 6C, int value = 108, char value = l or l
hexadecimal value = 6F, int value = 111, char value = o or o
hexadecimal value = 20, int value = 32, char value = or
hexadecimal value = 57, int value = 87, char value = W or W
hexadecimal value = 6F, int value = 111, char value = o or o
hexadecimal value = 72, int value = 114, char value = r or r
hexadecimal value = 6C, int value = 108, char value = l or l
hexadecimal value = 64, int value = 100, char value = d or d
hexadecimal value = 21, int value = 33, char value = ! or !
|
This example shows you another way to convert a hexadecimal string to an integer, by calling the Parse(String, NumberStyles) method.
string hexString = "8E2";
int num = Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
Console.WriteLine(num);
|
2274
|
Этот пример выполняет разбор string шестнадцатеричных значений и выводит символ, соответствующий каждому шестнадцатеричному значению. Сначала вызывается метод Split(array[]()[]) для получения каждого шестнадцатеричного значения как отдельной string в массиве. Затем вызывается метод ToInt32(String, Int32) для преобразования шестнадцатеричного значения в десятичное, представленное в формате int. В примере показано два разных способа получения символа, соответствующего этому коду символа. В первом случае используется ConvertFromUtf32(Int32), возвращающий символ, который соответствует целочисленному аргументу в виде string. По второму способу выполняется явное приведение int к char.
--
В следующем примере показан еще один способ преобразования шестнадцатеричной string в целое число путем вызова метода Parse(String, NumberStyles).
--
|