[Mono-dev] Implicit Polymorphy Question
Jonathan Pryor
jonpryor at vt.edu
Thu Sep 22 22:58:18 EDT 2005
On Thu, 2005-09-22 at 23:26 +0200, Samuel Abels wrote:
> On Do, 2005-09-22 at 18:45 +0200, Robert Jordan wrote:
> > You're looking for something like that (untested):
> > [...]
> > return d.DynamicInvoke (args);
> > [...]
>
> Thanks, I did not know this method before. I now implemented this using
> a combination of this and the Mono 2.0 generics support. Also Thanks to
> JD for mentioning this.
<snip icky code using BeginInvoke/>
With the introduction of anonymous delegates to C# 2.0, I think we need
to get more functional programmers involved. Throw in generics, and you
can do some some nifty type-safe delegate chaining:
// Functors with C# 2.0...
using System;
using System.Collections;
delegate T Generator <T> ();
delegate TRet Generator <TRet, TArg> (TArg arg);
class FunctorGen {
public static Generator<TRet> BindFirst <TRet, TArg> (Generator<TRet, TArg> gen, TArg arg)
{
return new Generator<TRet> (
new _FunctorInfo <TRet, TArg>(gen, arg).Invoke
);
// alas, my example of using an anonymous delegate as a
// generator function causes gmcs to die. :-(
// because this doesn't work, we need the _FunctorInfo class.
// return delegate { return gen (arg); };
}
private class _FunctorInfo<TRet, TArg> {
private Generator<TRet, TArg> gen;
private TArg arg;
internal _FunctorInfo (Generator<TRet, TArg> gen, TArg arg)
{
this.gen = gen;
this.arg = arg;
}
public TRet Invoke ()
{
return gen (arg);
}
}
public static void Main ()
{
Generator<void> c1 = BindFirst <void, ArrayList> (InvokeArrayList, null);
Generator<void> c2 = BindFirst <void, string> (InvokeString, "hello, world");
Generator<void> c3 = BindFirst <void, string> (
delegate (string s) {
InvokeString2 ("first string", s);
},
"second string"
);
c1 ();
c2 ();
c3 ();
}
private static void InvokeArrayList (ArrayList a) {}
private static void InvokeString (String a) {Console.WriteLine (a);}
private static void InvokeString2 (String a1, string a2)
{
Console.WriteLine (a1);
Console.WriteLine (a2);
}
}
Note that FunctorGen._FunctorInfo really shouldn't be necessary, as the
commented out code in FunctorGen.BindFirst should work. Alas, it causes
gmcs to vomit:
** ERROR **: file metadata.c: line 2736 (mono_type_size): assertion failed: (!gclass->inst->is_open && !gclass->klass->generic_container)
aborting...
Aborted
No nice short generator methods for me, but it should work eventually.
The real nice point is that the above can be done for *any* delegate
taking 0 or 1 parameters (supporting more isn't difficult, just make
more overloads of Generator and FunctorGen.Bind*), and you can pass
anonymous delegates as part of the original delegate to bind (as seen in
c3 for InvokeString2). All this, and completely compile-time type safe.
The only downside is that it requires a 2.0 runtime to execute, but it's
fun nonetheless.
- Jon
More information about the Mono-devel-list
mailing list