Code_Steel
Code_Steel

Reputation: 435

How to cast an int into a nullable type?

I'm just doing simple int swap program. I also just learnt about casting so I'm trying it out in this program. But I'm getting an error that says I should do an explicit cast.

I don't think I understand the concept of casts. What's the problem?

static void Main(string[] args)
{
    Console.WriteLine("Enter the FIRST Integer.");
    string tempint1 = Console.ReadLine();
    int int1 = Convert.ToInt32(tempint1);

    Console.WriteLine("Enter the SECOND Integer.");
    string tempint2 = Console.ReadLine();
    int int2 = Convert.ToInt32(tempint2);

    Console.WriteLine();

    int? swapInt = null;
    swapInt = (int)int1;
    int1 = int2;
    int2 = swapInt;

    Console.WriteLine("The integers have been swapped!");
    Console.WriteLine("The FIRST INTEGER is now " + int1);
    Console.WriteLine("The SECOND INTEGER is now " + int2);
    Console.WriteLine();
}

Upvotes: 2

Views: 3323

Answers (5)

Christos
Christos

Reputation: 53958

swapInt is a nullable int and below:

you try to assign an nullable int to an int that's the problem:

int2 = swapInt;

If you change it to to the following one it would be ok,

int2 = swapInt.Value;

Furthermore, this piece of code:

int? swapInt = null;
swapInt = (int)int1;
int1 = int2;
int2 = swapInt;

it could be changed to the following one:

 int? swapInt = int1;
 int1 = int2;
 int2 = swapInt.Value;

You don't have to cast an already integer to an int, (int)int1;

Update

I have to make a few comments about your program, which you could take them into acount.

static void Main(string[] args)
{
    // Get the users input.

    Console.WriteLine("Enter the FIRST Integer.");
    string a = Console.ReadLine();

    Console.WriteLine("Enter the SECOND Integer.");
    string b = Console.ReadLine();

    // Variables, in which we will store the parsed strings that user passes.
    int integerA;
    int integerB;

    // Try to parse the strings that user passes to create two integer numbers.
    // If either parse of a or parse of b fail, then the method Int32.TryParse()
    // will return false and the code in the body of if, will not be executed.
    if(Int32.TryParse(a, out integerA) && Int32.TryParse(b, out integerB))
    {
        // Pass the integers to the methods called swap
        Swap(ref integerA, ref integerB);
        Console.WriteLine("The integers have been swapped!");
        Console.WriteLine("The FIRST INTEGER is now " + int1);
        Console.WriteLine("The SECOND INTEGER is now " + int2);
    }

    Console.WriteLine();
}

// This methods makes the actual swap
static void Swap(ref int a, ref int b)
{
    int temp = a;
    a = b;
    b = temp;
}

If you read carefully the above code, then you will have noticed that we don't make use of nullables and actually, we don't need them at this case.

For your information, there is a generic method in C#, which can be used for swapping to objects either they are numbers or not. This method's name is Swap and it's signature is the following:

static void Swap<T>(ref T lhs, ref T rhs)

You can use this method as below:

Swap<int>(ref integerA, ref integerB);

For more information about this method, please have a look here.

What's ref stands for ?

As it is stated in MSDN:

The ref keyword causes an argument to be passed by reference, not by value. The effect of passing by reference is that any change to the parameter in the method is reflected in the underlying argument variable in the calling method. The value of a reference parameter is always the same as the value of the underlying argument variable.

Example let that we have a method called Increment:

public void Increment(int x)
{
    // This will increase the value of variable x by one.
    // This change is only visible insied the body of this method
    // and it is not reflected outside of it.
    x++;
}

If we had defined the method as below:

public void Increment(ref int x)
{
    x++;
}

the change in the value of x would have been visible also outside of the body of the method called Increment.

Why so?

Because in the first case we pass a copy of the value that is stored in x, while in the second case we don't pass a copy of this value. Hence any changes in the second case will be reflected also outside of the body of the method called Incerement.

Upvotes: 6

Nikhil Agrawal
Nikhil Agrawal

Reputation: 48568

You problem is in this line

int2 = swapInt;

int2 is an integer and swapInt is a nullable int or null?. You cannot assign like that because compiler cannot directly convert null? to null. Hence the error

Cannot implicitly convert type 'int?' to 'int'. An explicit conversion exists (are you missing a cast?)

When it cannot do so it asks for you to convert it.

So Change

int2 = swapInt;

to

if (swapInt.HasValue)
    int2 = swapInt.Value;

Nullable Types
Value types like int cannot be null. Nullable types are types which store value types and can be null.

To extract value from them first check whether they have value. This is done be checking HasValue. It returns a boolean and if it is true, we extract value using swapInt.Value.

You can cast like (int)swapInt but then it will throw exception if it does not have any value.

You can cast or get its value. Performance for both is same as cast is syntactic sugar for the Value property.

Upvotes: -1

Theodoros Chatzigiannakis
Theodoros Chatzigiannakis

Reputation: 29213

int? is a shorthand for a type called Nullable<int>. Obviously, then, int and Nullable<int> aren't the same type. Nullable<int> has a property called Value and that property is the actual int. To access the Value property, you should first check whether the HasValue property is true (just as you would check whether a reference type is not null).

Here's the problem, now:

There is an implicit conversion from int to Nullable<int> (remember, that's the same as int?) and that conversion says that a new Nullable<int> is created, with HasValue set to true and its Value set to the value of the initial int. Thus, you are allowed to do:

int a = 5
int? b = 5; // implicit conversion
int? c = a; // implicit conversion
int? d = c;

On the other hand, the opposite conversion, from Nullable<int> to int doesn't exist implicitly, because the Nullable<int> may have its HasValue property set to false, which means that a regular int won't be able to describe it and the compiler doesn't know what you'd want to happen in this case. So, this is why you can't do:

int? a = 5;
int b = a; // illegal, no implicit conversion exists

Instead, you'd want to do something like this:

int? a = 5;
if(a.HasValue)
{
    int b = a.Value;
    // ...
}
else
{
    // ...
}

Casts aren't related to the question (it's just a suggestion by the compiler, but it's not actually what you'd want to do here). For the sake of learning: a cast is simply an instruction to the compiler to treat an expression of one type as an expression of another (hopefully compatible) type, possibly by applying a conversion between those two types (if such a conversion is defined anywhere).

Upvotes: 6

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101681

The problem is that there is no implicit conversion from int? to int. Since int? can be null, compiler doesn't allow that, it wants from you to perform the cast explicitly:

int2 = (int) swapInt;

By doing this you are telling the compiler "I know what I'm doing.", if the swapInt is null this will throw exception at runtime.

Upvotes: 1

nraina
nraina

Reputation: 354

swapInt is a nullable type, the method GetValueOrDefault returns the value if not null else default value of the underlying type

int2 = swapInt.GetValueOrDefault()

Upvotes: -1

Related Questions