(1 item) |
|
(1 item) |
|
(5 items) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(6 items) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(4 items) |
|
(2 items) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(2 items) |
|
(5 items) |
|
(3 items) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(3 items) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(8 items) |
|
(2 items) |
|
(7 items) |
|
(2 items) |
|
(2 items) |
|
(1 item) |
|
(2 items) |
|
(1 item) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(5 items) |
|
(1 item) |
|
(3 items) |
|
(2 items) |
|
(2 items) |
|
(8 items) |
|
(7 items) |
|
(3 items) |
|
(7 items) |
|
(6 items) |
|
(1 item) |
|
(2 items) |
|
(5 items) |
|
(5 items) |
|
(7 items) |
|
(3 items) |
|
(7 items) |
|
(16 items) |
|
(10 items) |
|
(27 items) |
|
(15 items) |
|
(15 items) |
|
(13 items) |
|
(16 items) |
|
(15 items) |
I just tried posting this as a comment to Jon Skeet's blog, but the the CAPTCHA on MSMVPs seems to be completely broken... Either that, or it's right and I'm really not human. Since I was already planning to post about the fact that Jon is now blogging, I thought I might as well just post my comment here anyway. Jon already has a great C# resources page, and I'm expecting his blog to be well worth reading, and his first few posts don't disappoint. What follows is a reply to his "Nasty generics restriction" article.
In essence, Jon is really saying he'd rather be using ML. :) Here's the ML version of his doItTwice function:
fun doItTwice x y = x (x (y));
Here's the static type inferred by the ML compiler when given that function definition:
val doItTwice = fn : ('a -> 'a) -> 'a -> 'a
That is to say, doItTwice
is a function whose first parameter is a function whose
type is 'a -> 'a
. (I.e. a function whose return type is the same as
its parameter type. And that's all we know - we don't know what the actual type being passed in at this stage is. This
is polymorphic code, so it doesn't care what the specific parameter/return type is.)
doItTwice
's second parameter must be the same type as whatever the function passed in
expects as a parameter. doItTwice
will return a value of that self same type.
(It would be interesting to see what F# does with this. F# is a .NET language that lets you do this kind of thing. My guess is that what happens in F# stays in F#, so it doesn't have to solve the problem of how to map this into the world of .NET and delegates. I've not got around to installing F# yet, so I could be wrong.)
Of course you can write such a method in C# with generics:
public static T DoItTwice<T> (Func<T,T> func, T input) { return func(func(input)); }
And we can even define a generic delegate type that can refer to such a thing:
public delegate T Applier<T>(Func<T, T> func, T input);
and we can initialize variables of this type:
Applier<int> appInt = DoItTwice<int>; Applier<string> appString = DoItTwice<string>;
But I think the thing Jon wants is to have a delegate instance refer to this generic method without committing to the generic type parameters. Something like this:
Applier<T> appT = DoItTwice<T>;
or whatever syntax you deem fit...
Which brings me to my question for Jon - moving out of the realm of lambda syntax for a moment, what would you expect a variable declaration for one of these things to look like? I don't think my example above is right, because that syntax already
means something. At least it does if I've got some type called T
already... I don't know what syntax Jon will
ask for, but I suppose it could look like this:
Applier<T> appT<T> = DoItTwice<T>;
Note the generic syntax applied to the variable name itself.
This implies the introduction of variables and/or fields that can hold a reference to any instance of a generic. This is subtly different from what we can do with .NET generics today. I'm not sure if Jon's asking for this, or just a solution for lambdas and/or delegates. Or something else...