cjmarsh
cjmarsh

Reputation: 292

Why is casting in certain generic circumstances necessary?

In a generic method you need to cast your return variable to an object and then back to the generic type and I understand why that is generally, but what I don't understand is why you need to do that when you've already established what type the variable is in the scope of the return statement. For example, normally I'd do this:

public MyType1 obj1;
public MyType2 obj2;

public T GetObject<T>()
{
    if (obj1 is T) return (T)(object)obj1;
    else if (obj2 is T) return (T)(object)obj2;
    else return default(T);
}

But my question is, why can't I remove the casting like this:

public MyType1 obj1;
public MyType2 obj2;

public T GetObject<T>()
{
    if (obj1 is T) return obj1;
    else if (obj2 is T) return obj2;
    else return default(T);
}

Why doesn't the compiler understand that the object is of the correct return type when that's the only type it could be?

Upvotes: 1

Views: 140

Answers (3)

Dai
Dai

Reputation: 155055

Avoid foo is T; (T)foo expressions. Use the as operator and it solves your problems:

public MyType1 obj1;

public T GetObject<T>() where T : class {
    T ret = obj1 as T;
    if( ret != null ) return ret;
    ret = obj2 as T;
    if( ret != null ) return ret;
    return default(T);
}

Upvotes: 1

heijp06
heijp06

Reputation: 11788

According to the C# Reference:

The is keyword causes a compile-time warning if the expression is known to always be true or to always be false, but typically evaluates type compatibility at run time.

That is whether obj1 is of type T is not determined by the compiler but is evaluated when the code runs.

Upvotes: 3

Ashley Frieze
Ashley Frieze

Reputation: 5443

You are making incorrect assumptions about generics. To understand this better, imagine this. Let's say you had a base class Base and two sub classes, Sub and VerySub.

If your members were stored as Base then the compiler can only guarantee they are Base. It is the static typing system which generics use. At run time let's say we had a simple function called GetIfVerySub. Let's say it did a test on an object of type Base and discovered it was also a VerySub. That's unknowable at compile time, so to return the downcasted object, you would expect to do a cast or an as.

This is exactly what your generic function is trying to do, but owing to the fact it is generic, it also can work on any type, including ones incompatible with Base.

The better question, though, is why you are doing this at all?

Upvotes: 3

Related Questions