cannot convert type 'string' to 'int?' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion or null type conversion

StackOverflow https://stackoverflow.com/questions/887943

  •  23-08-2019
  •  | 
  •  

Question

C# accepts the following:

object o = "hello";
int? i = o as int?;

if (i == null) {
    // o was not a boxed int
}
else {
    // Can use i.Value to recover the original boxed value
}

But not

String o = "hello";
int? i = o as int?;

if (i == null) {
    // o was not a boxed int
}
else {
    // Can use i.Value to recover the original boxed value
}

I'm just wondering about the behaviour of the keyword as in C#.

The same as in Java this would fail:

Object test1 = "hello";
Integer test2 = (Integer) test1;
String test3 = "hello";
Integer test4 = (Integer) test3; //compilation error
Was it helpful?

Solution

The compiler knows that a string can never be an int? so it tells you that. That doesn't mean that int? isn't useful. Your attempted use case is far from the normal one. The normal one is "I want to represent an integer and the possibility that the value is missing/unknown". For that, int? works extremely well.

Why would you expect your original code to work? Why would it be helpful?

Note that you can use as with nullable types, for unboxing:

object o = "hello";
int? i = o as int?;

if (i == null)
{
    // o was not a boxed int
}
else
{
    // Can use i.Value to recover the original boxed value
}

EDIT: Having seen your comment, you don't use as to parse things. You probably want to use int.TryParse:

string text = "123":
int value;
if (int.TryParse(text, out value))
{
    Console.WriteLine("Parsed successfully: {0}", value);
}
else
{
    Console.WriteLine("Unable to parse text as an integer");
}

If you're sure the string is meant to be an integer (i.e. it's a bug otherwise) then you can just use int.Parse:

int value = int.Parse(text);

That will throw an exception if the parsing fails.

Note also that both of these methods allows you to specify a format provider (usually a culture info) which allows you to express how numbers are expressed in that format (e.g. thousands separators).

EDIT: In answer to your new question, the compiler prevents this because it knows a string can't possibly be a boxed int - the conversion will never ever succeed. When it only knows that the original value is an object, it might succeed.

For instance, suppose I said to you, "Here's a shape: is it a square?" That's a sensible question. It's reasonable to ask it: you can't tell without looking at the shape.

If, however, I said: "Here's a triangle: is it a square?" Then you'd be reasonably entitled to laugh in my face, as a triangle can't possibly be a square - the question doesn't make sense.

OTHER TIPS

int? means a nullable integer type, not an int that could contain any other type of variable.

If you want a variable type that could contain an int or a string, you'd have to use an object, or a string I suppose, and then live a life filled with type casting. I don't know why you would want to do that, though.

int? allows you to store any integer value, or a null value. Which is useful when say the answer to the question "How many orders has this person placed" is legitimately "I don't know" instead of a number of orders, or zero which would be "I know for a fact this person has never placed an order".

I want to add some further information.

An other case, why the cast is invalid and the compiler throws an error on compilation is, that System.String is marked as sealed. So the compiler knows from which types System.String inherites and to which types you can cast the string using the as-operator.

Due to the keyword sealed, the compiler also knows that you cannot inherit from System.String to add functionality or implement some additional interfaces.

The code below is an example and the compiler will throw the following error on compilation

Cannot convert type 'SealedClass' to 'ICastToInterface' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion

public class UnsealedClass {
  // some code
}

public sealed class SealedClass {
  // some code
}

public interface ICastToInterface {
  // some code
}

public class Test {

  public Test() {
    UnsealedClass unsealedClass = new UnsealedClass();

    SealedClass sealedClass = new SealedClass();

    ICastToInterface unsealedCast = unsealedClass as ICastToInterface;  // This works fine

    ICastToInterface sealedCast = sealedClass as ICastToInterface; // This won´t compile, cause SealedClass is sealed
  }
}

but you can check the value of null and set it to null.

int? blah;
if (blah == null)
{}

int? is a nullable integer, it has nothing to do with casting and the as keyword. "String" is a string type object, which is not convertible to an int (nullable or non-nullable).

The as Keyword is virtually the same as casting using brackets except it will not return an error, it will set the object to null:

int i = 1;

object o = i; //boxing

int j = (int)o; //unboxing

This first example works as the object assigned to o is an int.

Now consider:

string i = "MyString";

object o = MyString;

 int j = (int)o //unboxing raises exception

 int j = o as int; //raises compilation Error as int is not nullable
 int? j = o as int?; /// o == null

I hope that that helps to explain the difference between the two concepts.

Richard

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top