I was reading an interview with Joshua Bloch in Coders at Work, where he lamented the introduction of generics in Java 5. He doesn't like the specific implementation largely because the variance support—Java's wildcards—makes it unnecessarily complex.
As far as I know, C# 3 doesn't have anything like explicit, bounded wildcards, e.g. you can't declare a method PriceBatch that takes a collecton of Asset or any Asset subclass (void PriceBatch(Collection<? extends Asset> assets)
in Java?).
Does anyone know why wildcards and bounds haven't been added to C#? Were these features intentionally left out to make the language simpler, or is this something they just haven't gotten around to implement yet?
EDIT: Holy smoke, comments from Eric Lippert himself! After reading his and Paul's insightful comments, I realize that at least upper bounds are supported and that the above example can be translated to C# as:
void PriceBatch<T>(ICollection<T> assets) where T : Asset
Lower bounds, on the other hand, are apparently not supported as Eric says in his second comment, e.g. there is probably no way to directly translate this (somewhat contrived) Java code to C#:
public class Asset {}
public class Derivative extends Asset {}
public class VanillaOption extends Derivative {}
public static <T extends Asset> void copyAssets(Collection<T> src, Collection<? super T> dst) {
for(T asset : src) dst.add(asset);
}
Collection<VanillaOption> src = new ArrayList<VanillaOption>();
[...]
Collection<Derivative> dst = new ArrayList<Derivative>();
[...]
copyAssets(src, dst);
Am I correct? If this is the case, is there a particular reason why C# has upper but not lower bounds?
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.
A complicated question.
First let's consider your fundamental question, "why is this illegal in C#?"
class C<T> where T : Mammal {} // legal
class D<T> where Giraffe : T {} // illegal
That is, a generic type constraint can say "T must be any reference type that could be assigned to a variable of type Mammal", but not "T must be any reference type, a variable of which could be assigned a Giraffe". Why the difference?
I don't know. That was long before my time on the C# team. The trivial answer is "because the CLR doesn't support it", but the team that designed C# generics was the same team that designed CLR generics, so that's really not much of an explanation.
My guess would be simply that as always, to be supported a feature has to be designed, implemented, tested, documented and shipped to customers; no one ever did any of those things for this feature, and therefore it is not in the language. I don't see a large, compelling benefit to the proposed feature; complicated features with no compelling benefits tend to be cut around here.
However, that's a guess. Next time I happen to chat with the guys who worked on generics -- they live in England, so its not like they're just down the hall from me, unfortunately -- I'll ask.
As for your specific example, I think Paul is correct. You do not need lower bound constraints to make that work in C#. You could say:
void Copy<T, U>(Collection<T> src, Collection<U> dst) where T : U
{
foreach(T item in src) dst.Add(item);
}
That is, put the constraint on T, not on U.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With