﻿# Boxing and Unboxing in C\#

Boxing and unboxing allow developers to convert value types to reference types and vice versa\. These operations can reduce performance due to additional calculations, such as allocating memory for a new object and copying data\.

## Boxing

Boxing occurs when a value type is converted to the _System\.Object,_ _System\.Enum_, _System\.ValueType_, or interface_ _type\. This operation can be explicit or implicit:

```cpp
int a = 10;
object b = a;          // Implicit boxing
object c = (object)a;  // Explicit boxing
```

Implicit boxing occurs when we use a value\-type variable where a reference type is expected\. Let's look at the examples of such operations:

* calling a method with reference\-type parameters and value\-type arguments;
* calling methods of the base reference type of value\-type instances;
* declaring a reference\-type variable with initialization of a value\-type instance\.

You can find some detailed examples below\.

**Example 1**

```cpp
struct Point : IComparable<Point>
{
  .... 
  public int CompareTo(Point point) { .... }
}

static void 
ProcessComparableItems<T>(IComparable<T> lhs,
                          IComparable<T> rhs)
{ .... }

static int Calculate(....)
{
  var firstPoint = new Point(....);
  var secondPoint = new Point(....);
  ProcessComparableItems(firstPoint, secondPoint);
  ....
}
```

The _ProcessComparableItems_ method handles two _IComparable<T\>_ parameters\. At the same time, the _Point_ structure implements this interface\. However, if we call the _ProcessComparableItems_ method with arguments of the _Point_ type, each of them is boxed:

```cpp
// ProcessComparableItems(firstPoint, secondPoint);
IL_0039: ldloc.0
IL_003a: box BoxingTest.Program/Point  // <=
IL_003f: ldloc.1
IL_0040: box BoxingTest.Program/Point  // <=
IL_0045: call void 
  BoxingTest.Program::ProcessComparableItems
    <valuetype BoxingTest.Program/Point>(....)
....
```

**Example 2**

```cpp
var dateTime = new DateTime(....);
Type typeInfo = dateTime.GetType();
```

_dateTime_ is a variable of the \(_DateType_\) value type\. The _GetType_ method of _dateTime_, defined in the _System\.Object_ type, is called\. To call the method, we need to perform boxing of the _dateTime_ object:

```cpp
// Type typeInfo = dateTime.GetType();
IL_0014: ldloc.0
IL_0015: box [System.Runtime]System.DateTime // <=
IL_001a: call instance class
  [System.Runtime]System.Type
  [System.Runtime]System.Object::GetType()
....
```

## Unboxing

Unboxing is the conversion of a boxed reference type back to a value type\. Unboxing has some peculiarities:

* Unboxing must be done to exactly the same data type that was boxed\. Unboxing to an incompatible value type causes an _InvalidCastException_\.
* Attempting to unbox a null reference causes a _NullReferenceException_\.

**Example: **

```cpp
double a = 1;
object b = a;
int c = (int)b;
```

Unboxing a variable to an incompatible value type causes _InvalidCastException_\. Here is the fixed code:

```cpp
int c = (int)(double)b;
```

## Additional Resources

* [Check how you remember nullable value types\. Let's peek under the hood](https://pvs-studio.com/en/blog/posts/csharp/0772/)
* [Enums in C\#: hidden pitfalls](https://pvs-studio.com/en/blog/posts/csharp/0844/)
* [Does C\# always have boxing with string concatenation and interpolation?](https://pvs-studio.com/en/blog/posts/csharp/1060/)
* [V3148: Casting potential 'null' value to a value type can lead to NullReferenceException\.](https://pvs-studio.com/en/docs/warnings/v3148/)