Пример результатов выполнения
Execution Succeded
return value = 0
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:
int i = 123; |
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 или любой другой тип интерфейса, реализуемый этим типом значения. При упаковке типа значения в куче выделяется экземпляр объекта и выполняется копирование значения в этот новый объект.
|
|
Рассмотрим следующее объявление переменной типа значения.
int i = 123; |
Следующий оператор неявно применяет операцию упаковки к переменной 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:
int j = (short) o; |
to:
int j = (int) o; |
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.
При изменении оператора
int j = (short) o; |
на
int j = (int) o; |
будет выполнено преобразование со следующим результатом.
Unboxing OK.
Дата добавления: 2019-03-09; просмотров: 259; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!