Constrained Generics and Return Values

I was working on some mocking stuff today and I ran into an odd situation. Let's say you have the following class hierarchy:

public abstract class Cup
{
}

public class CoffeeCup : Cup
{
}

public class Shotglass : Cup
{
}

Now, let's define a factory that randomly creates cups:

public static class CupCreator
{
    public static T Create<T>() where T : Cup
    {
        if(DateTime.Now.Second % 2 == 0)
        {
            return new Shotglass();
        }
        else
        {
            return new CoffeeCup();
        }
    }
}

The problem is, the two return statements are in error - here's what the error statement looks like:

Cannot implicitly convert type 'Shotglass' to 'T'

It's error CS0029.

Here's the funny thing. 10 years ago, I would've assumed that there's something wrong with the compiler. I'm older now and I know that I'm probably the idiot :).

When I first did this, I thought, OK, T must be at least a Cup...so returning a CoffeeCup or a Shotglass should be OK, right?

Well, no. What if I call it like this?

var shot = CupCreator.Create<Shotglass>();

Then returning a CoffeeCup is invalid.

Just because T is constrained to be a Cup and the two return types descend from Cup doesn't mean the code is valid. It took me a bit to figure this one out!

* Posted at 08.18.2008 03:25:43 PM (Last Update: 08.19.2008 10:05:01 AM) | 2 comments | Link | RSS *

Comments

# clever compiler, from chuck at 08.18.2008 05:38:00 PM

Took me a while to see it. That's a pretty clever compiler. The compiler has to have a lot more rules to cover today, than 15 years ago in the world of C.

# How about returning Cup?, from Jason Haley at 08.19.2008 10:04:57 AM

Does it work if you return type Cup instead of T?

Add a Comment

(*) = Required field
Name (*):

E-Mail (*):

Web Site:

Title (*):

Comments (*):

Enter the code you see (*)



Quote
"Nature knows no indecencies; man invents them." Mark Twain
Twitter History
follow me on Twitter
Blog History