I have this:

public IClub GetTeam()
{
    return new Arsenal();
}
//compiles since Arsenal is an IClub

public T GetTeam<T>() where T : IClub, new()
{
    return new Arsenal();
}
//wouldn't compile saying "cannot convert Arsenal to T"

But these things work:

public T GetTeam<T>() where T : IClub, new()
{
    T t = new T();
    t.Sponsor = "Nike"; //since it knows T is IClub,
    return new T();     //but why the injustice to return type alone?
}
  1. Why wouldn't the second code block compile even though return type is anyway IClub? Isn't that injustice?

  2. I know I am not fully utilizing the potential of type constraints in above code but what is an alternative to get the code running?

2

There are 2 answers

2
Botz3000 On BEST ANSWER

It's because at compile time the compiler does not know whether Arsenal will be convertible to T. T could be another type implementing IClub after all. like in GetTeam<WhateverTeam>(). WhateverTeam implements IClub, but you cannot convert Arsenal to that.

You'd have to cast the result if you want your code to compile (as in Marc-André's answer), but you should rather rethink your design (also calling GetTeam<WhateverTeam>() would result in an exception). Making that method generic doesn't make sense if you already know which type you will return.

6
LightStriker On

T is an unknown type at compile time and the compiler have no way to know if they can be cast from one type to another, so you much explicitly call for a cast toward that type.

return (T)(object)(new Arsenal());

This way, the compiler know for sure that Arsenal can be cast as an object, and that object can be cast as T. You will get a runtime assert if the cast is invalid, but it will compile and work fine if it cast correctly.

Why T is unknown if you constraint it to IClub? Because any type could implement this interface. You try to return Arsenal, but another class, let's say "Car : IClub" also implement IClub. In this case, T can be Car, but the compiler has no way to prove that Arsenal could be cast into Car... Or any other class for that matter as it only knows which interface it implement, not it's real identity.