Reputation: 435
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
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
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
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
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
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