http://nullprogram.com/blog/2014/04/01/ tries to explain that Java's generics can't simulate duck typing with an example:
class Caller<T> { final T callee; Caller(T callee) { this.callee = callee; } public void go() { callee.call(); // compiler error: cannot find symbol call } } class Foo { public void call() { System.out.print("Foo"); } } class Bar { public void call() { System.out.print("Bar"); } } public class Main { public static void main(String args[]) { Caller<Foo> f = new Caller<>(new Foo()); Caller<Bar> b = new Caller<>(new Bar()); f.go(); b.go(); System.out.println(); } }
The program will fail with a compile-time error. This is the result of type erasure. Unlike C++’s templates, there will only ever be one compiled version of
Caller
, andT
will becomeObject
. SinceObject
has nocall()
method, compilation fails.
Does it mean that by Java generics, the methods of a type parameter are limited to the methods of class java.lang.Object
?
C#'s generics is implemented in terms of reification instead of type erasure. Does C#'s generics not have the above limitation as Java's generics? So can C#'s generics actually achieve the same thing as duck typing?
Thanks.
No. But C#'s generics can include a constraint where the type parameter is restricted to inherit or implement some particular type. When that's done, any expression of the type of that type parameter is resolved as the constrained type and members from that type can be accessed.
This is similar to the
extends
constraint described in the article you read.The only duck-typing support in C# is the
dynamic
keyword, where final compilation of expressions involvingdynamic
values is deferred until runtime when the actual runtime type is known.Related reading:
Trivial C# class with a generic parameter wouldn't compile for no apparent reason
Call a method of type parameter