Magpie
Magpie

Reputation: 7173

Generics and Casting

Why does the following compile?

public IList<T> Deserialize<T>(string xml)
{              
    if (typeof(T) == typeof(bool))
        return (IList<T>)DeserializeBools(xml);

    return null;
}

private static IList<bool> DeserializeBool(string xml) { ... do stuff ... }

But this doesn't

public MyClass<T> GetFromDb<T>(string id)
{
    if (typeof(T) == typeof(bool))
        return (MyClass<T>)GetBoolValue(id);  <-- compiler error here

    return null;
}

private static MyClass<bool> GetBoolValue(string id) { ... do stuff ... }

Upvotes: 11

Views: 2204

Answers (3)

Jon Skeet
Jon Skeet

Reputation: 1503869

The reason interfaces work is that any object might implement IList<T> (unless it's known to be an instance of a sealed type which doesn't implement it, I guess) - so there's always a possible reference type conversion to the interface.

In the latter case, the compiler isn't willing to do that because it doesn't really know that T is bool, despite the previous if statement, so it doesn't know what conversion to try between MyClass<T> and MyClass<bool>. The valid conversions to generic types are pretty limited, unfortunately.

You can fix it fairly easily:

return (MyClass<T>)(object) GetBoolValue(id);

It's ugly, but it should work... and at least in this case it won't be causing any boxing.

Upvotes: 20

Benjamin Confino
Benjamin Confino

Reputation: 2374

What happens if you replace

return (MyClass<T>)

with

return (MyClass<bool>)

Upvotes: 0

Den
Den

Reputation: 1912

C# 4.0 allows declaration of covariance and contravariance on parameterized interface and delegate types.

Upvotes: 0

Related Questions