Oh so you want polymorphism ???
Mon, Nov 5 2007 15:47
I recall almost four years ago to this day, I was at the 2003 PDC in LA. On the last day of the conference, the head architects of different .NET languages got together and talked about language directions, generics and some of the "VS 2005" stream of things. There was a Q&A session at the end, and I stood in line to ask a question about generics. They were about to cut off all questions, but I managed to ask the final question for the day. I asked about generics and "polymorphism". Anders didn't seem to quite get what I meant at first, then when I gave the example of being able to treat IList(of Apple) as IList(Of Fruit), he said "oh you mean generic covariance and contravariance" or words to that effect. The reply was no, saying the cost would be too high although he did suggest one of the other less common languages on .NET (no not VB <g>)
Fast forward four years, and now the C# team are finally talking about this ! At first I thought cool, Eric and the C# team are onto this. Then around his seventh or eight post on the topic he started to loose me as it seems they've shifted the focus on to a new syntax for defining the interfaces, which isn't really going to address the issue IMO. And I question just how that will surface in the IDE, and whether T is + or - really even makes sense at the interface level as it really needs depends on whether T is a return value or a parameter. Potentially I could see some advantage there, probably to do with that functional programming cloud, but it seems to have drifted away from the real need.
The most common need I see is when you have things such as a List(Of Customer) and you want to work with it as a List(Of BusinessBase). It's also especially difficult when you are passed the list as an Object, such as from a DataSource and you want to check to see if it is a IList(of BusinessBase). Really what we need is a view of the object.
Some views are safe, such as treating an IEnumerable(Of Customer) as IEnumerable(Of BusinessBase), but others are not, such as IList(Of Customer) to an IList(Of BusinessBase), but for the most part when we want those views we are interested in only the safe part. It's not like we can retrospectively change IList, or that at present we could have one Interface definition for the Item Get, and another for the Item Set. What would be nice is being able to use a view, and the compiler/IDE warn if you use any of the unsafe part, like Item Set, or if you pass the view to a method etc, yet allow you safely to do things such as access Count, get the Items and do operations on them as if they were business object base classes. These things are safe, yet today generics does not allow for that (note if you have generic parameters cascading throughout this issue does not arise, but that doesn't work with Object parameters, or current event design etc)
So some psuedo verbose code to explain what I would like:
' assume datasource is As Object, but is a IList(Of Customer)
If datasource IsViewable As IList(Of BusinessBase) Then
Dim view As ViewOf IList(Of BusinessBase) = ViewOf( datasource, IList(Of BusinessBase))
For i As Int32 = 0 to view.Count - 1
view(i).Validate ' legal as Validate is defined on BusinessBase
Dim temp as BusinessBase = view(i) ' legal
view(i) = temp ' compiler warning of potential runtime error
Likewise you could create a ViewOf IList(Of Customer) from an IList(Of Person), but here the inverse would apply in code, meaning you could add a customer to the datasource, but you'd get a warning treating a person as a customer as that might not be the case.
If the datasource is as object though, the compiler can't know if the datasource is contra or co variant to the view. By default a "View" should be treated as a widening, that is a ViewOf IList(of BusinessBase), would mean the datasource is assumed to be a ViewOf IList(Of DerivedFromBusinessBase). The same rules for variance as we see today with delegate variance would apply. If the view wanted was one that is potentially unsafe, such as IList(Of Customer) from an IList(Of Person) then the view should be specified as a NarrowingView.
I don't want to redefine IList, or have to mess with defining which generic parameters are covariant and contravariant and where. What I want is to be able to deal with generic types with variance and create views such as the compiler tells me what is and isn't legal with that view, what's safe and what isn't. And most importantly it has to work with existing generic types and interfaces out there today.
So perhaps my response is four years late, but no I don't mean contravariance and covariance, I mean polymorphism :)