Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I cast int to T, but can cast int to object and then object to T?

This code does not compile:

public T Get<T>()
{
    T result = default(T);
    if(typeof(T) == typeof(int))
    {    
        int i = 0;
        result = (T)i;
    }

    return result;
}

however, this code does compile:

public T Get<T>()
{
    T result = default(T);
    if(typeof(T) == typeof(int))
    {    
        int i = 0;
        result = (T)(object)i;
    }

    return result;
}

The code also works fine. I don't understand why the compiler can cast an object (actual type could be anything) to T, but cannot cast an int (which inherets from object) to T.

like image 858
Matthijs Wessels Avatar asked Dec 23 '11 19:12

Matthijs Wessels


People also ask

How do you cast an integer to an object?

If your object is a String , then you can use the Integer. valueOf() method to convert it into a simple int : int i = Integer. valueOf((String) object);

Can integer be cast to number Java?

You can't cast from int to Number because int is a primitive type and Number is an object. Casting an object is changing the reference type from one type of object to another.

When an integer object is added to a string object?

You can't cast an Integer to a String because they are not related. You can only cast a referece to one of its superclasses, ie: upcasting, in which case the cast operator is not needed, or its subclasses (downcasting). Integer is neither a subclass nor a superclass of String , so you can't do that.


2 Answers

As SLaks says, the compiler knows that T is convertible to object but that's only half of it. The compiler also knows that any object of type T derives from object, so it needs to allow downcast from object to T. Collections pre v2.0 needed this. Not to T of course but to be able to downcast from object to any type. It would have been impossible to get anything out of a collection as anything else than an object.

The same is not true when talking about T and int. Your code is of course safe from those problems at runtime due to the if statement, but the compiler can't see that. In general (not in this case though) proving that you will never get to the body of an if in the case of some external condition being true is NP-complete and since we wish the compiler to complete at some point, it's not going to try and basically solve a millennium prize problem

There are many scenarios where substituting a specific type for T would not be allowed in non-generic code.

If you can't write the code as non-generic for any substitution of T with a specific type, it's not valid, not just in this case but generally. If you know that for all your use cases of the method it would actually be valid, you can use constraints to your generic method.

like image 77
Rune FS Avatar answered Sep 28 '22 07:09

Rune FS


The compiler doesn't know that T is int. (even though you just proved that it is int in your if)

By contrast, the compiler does know that T is always convertible to object.

For example, if T is string, it's still convertible to object, but it's not convertible to int.

like image 35
SLaks Avatar answered Sep 28 '22 07:09

SLaks