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

25,277

Solution 1

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.

Solution 2

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".

Solution 3

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
  }
}
Share:
25,277
Admin
Author by

Admin

Updated on July 10, 2022

Comments

  • Admin
    Admin almost 2 years

    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
    
  • kscott
    kscott almost 15 years
    because you are trying to assign a string value to an int. the question mark just allows int to contain a null value, it does not change the fact that it is an int.
  • Jon Skeet
    Jon Skeet almost 15 years
    Juan: You don't use a cast or "as" to convert between strings and other types. There isn't an implicit or explicit conversion available - you have to use a parsing method. See the second half of my answer for details and an example.
  • Jon Skeet
    Jon Skeet almost 15 years
    Nope - I would never have expected a conversion operator to try to do parsing. Oops - it looks like I misread your edited question, I thought it said you were trying to find a way to do the conversion. I'll leave the extra info there for future readers though.
  • Jon Skeet
    Jon Skeet almost 15 years
    "int j = o as int" doesn't raise an exception - it prevents compilation, because there's no value for j to take in the case where o isn't a boxed int.
  • Richbits
    Richbits almost 15 years
    Sorry, thanks for the correction Jon... I've updated the answer correspondingly... (hopefully correctly)
  • Jon Skeet
    Jon Skeet almost 15 years
    It's a pleasure to write them too :)
  • Jon Skeet
    Jon Skeet almost 15 years
    No, I think it's fine - it's an explicit conversion, so you're telling the compiler "I think this will be okay at execution time". It makes perfect sense to me that you can't tell the compiler you think something will work when the compiler knows for certain that it won't.