Most of modern object oriented languages now support generics since C++ introduced it. More and more programmers found its useful and flexible to design advanced concepts as well as lots of useful libraries came out after famous C++ STL.
Honestly, I haven't had deep knowledge or experience on it but started using it since all the languages I'm handling have it as core role of features.
Recently, I've deployed lots of abstract types to design multiple modules completely decoupled to each other and needed to introduce generic list of such abstract type since C# support list using generics like following.
List<IDeviceDetail> getDeviceDetailList()
{
...
}
In fact, we have LINQ statements inside of the method which returns a list of generics.
var details = from p in context.DeviceDetail
select p;
where details can return a type of IList<DeviceDetail> when we call ToList().
I finished up this method like this without any doubting
List<IDeviceDetail> getDeviceDetailList()
{
var details = from p in context.DeviceDetail
select p;
return details.ToList();
}
and… it caused compile error.

Ooops! What's wrong with it? Must be a casting problem? But casting doesn't even help this problem.
I asked couple of my friends, searched Google, IBM developerworks(1) and finally concluded this is not allowed in any language!
I'll explain in short for those who don't want to navigate to different page to read it.
By allowing Covariance Generics, we can allowing invalid assignment in the future.
For example, assume we have BabyPatient and AdultPatient which implement IPatient (or inherit PatientBase)
Then following thing can happen by allowing Covariance Generics
interface IPhysician {...}
class Pediatrician: IPhysician {...}
class Surgeon: IPhysician {...}
...
IList<IPhysician> pediatricians=new IList<Pediatrician>(); // 1
IList<IPhysician> physicians=pediatricians; // 2.. which is illegal
physicians.Add(new Surgeon()); // 3
Since physicians is type of IList<IPhysician>, it's perfectly legal to append a Surgeon to its list. This breaks type safety because physicians actually refers to pediatricians which is list of Pediatrician.
The only workaround to this is to reinitialize new list completely and there's little useful utility(3) to do this.
public class EnumerableGeneric<TClass, TInterface> : IEnumerable<TInterface>
where TClass : TInterface
{
private IList<TClass> list;
public EnumerableGeneric(IList<TClass> list)
{
this.list = list;
}
public IEnumerator<TInterface> GetEnumerator()
{
foreach (TClass item in list)
yield return item;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
using this I could complete my method like following
List<IDeviceDetail> getDeviceDetailList()
{
var details = from p in context.DeviceDetail
select p;
return EnumerableGeneric<DeviceDetail, IDeviceDetail>(details.ToList()).ToList();
}
It's not a perfect solution since we're using two different copies of objects, now.
Maybe it's a design problem rather than a language feature.
Keep in mind that Covriance Generics is not allowed.
Post preview:
Close preview