c# - A Generic Pass-Through Interface. Is this possible? -
what wouldn't give have work:
public interface icallback { void handle<t>(t arg); } public class messagehandler : icallback { public void handle<t>(t arg) { string name = typeof(t).name; console.writeline(name); } public void handle(int arg) { string name = "wow, int"; console.writeline(name); } } public class worker { public void dosomething(icallback cb) { cb.handle(55); } } //... worker foo = new worker(); icallback boo = new messagehandler(); //i want print "wow, int" foo.dosomething(boo)
unfortunately, calls generic entry point rather "specialized" entry point. well, thats interfaces you.
i've tried same approach replacing int-specific signature generic signature mojo
specific:
public void handle<t>(t arg) t : mojo {}
i hoping sufficient form "special override" if argument of type mojo
. compiler complains have 2 methods same signature (one mojo
specific, other open-ended). well, hoping think "the same signature" both fulfill interface , "best" selected @ run-time. ah well.
in effect, i'm trying achieve vaguely similar "traits," "else-if-then of c++". guess considered form of "interface signature contravariance."
i'd love discover there special c# keyword enables capability, or featured addition c# in .net 4.5.
yes, no? comments?
try changing worker
class this:
public class worker { public void dosomething(icallback cb) { ((dynamic)cb).handle(55); } }
[edit]
just know, adding innocuous-looking "dynamic" severely changes output code. invokes compiler @ run-time dynamic thing.
i draw attention comments , other answers here. recommend read them , understand why doing above might not such great idea.
further, noted in answer below, constraining argument type icallback
will still allow runtime errors if handle()
method implemented explicitly.
here's il simple-looking method:
.method public hidebysig instance void dosomething(class consoleapplication1.icallback cb) cil managed { .maxstack 9 .locals init ( [0] class [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfo[] cs$0$0000) l_0000: nop l_0001: ldsfld class [system.core]system.runtime.compilerservices.callsite`1<class [mscorlib]system.action`3<class [system.core]system.runtime.compilerservices.callsite, object, int32>> consoleapplication1.worker/<dosomething>o__sitecontainer0::<>p__site1 l_0006: brtrue l_0058 l_000b: ldc.i4 256 l_0010: ldstr "handle" l_0015: ldnull l_0016: ldtoken consoleapplication1.worker l_001b: call class [mscorlib]system.type [mscorlib]system.type::gettypefromhandle(valuetype [mscorlib]system.runtimetypehandle) l_0020: ldc.i4.2 l_0021: newarr [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfo l_0026: stloc.0 l_0027: ldloc.0 l_0028: ldc.i4.0 l_0029: ldc.i4.0 l_002a: ldnull l_002b: call class [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfo [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfo::create(valuetype [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfoflags, string) l_0030: stelem.any [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfo l_0035: ldloc.0 l_0036: ldc.i4.1 l_0037: ldc.i4.3 l_0038: ldnull l_0039: call class [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfo [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfo::create(valuetype [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfoflags, string) l_003e: stelem.any [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfo l_0043: ldloc.0 l_0044: call class [system.core]system.runtime.compilerservices.callsitebinder [microsoft.csharp]microsoft.csharp.runtimebinder.binder::invokemember(valuetype [microsoft.csharp]microsoft.csharp.runtimebinder.csharpbinderflags, string, class [mscorlib]system.collections.generic.ienumerable`1<class [mscorlib]system.type>, class [mscorlib]system.type, class [mscorlib]system.collections.generic.ienumerable`1<class [microsoft.csharp]microsoft.csharp.runtimebinder.csharpargumentinfo>) l_0049: call class [system.core]system.runtime.compilerservices.callsite`1<!0> [system.core]system.runtime.compilerservices.callsite`1<class [mscorlib]system.action`3<class [system.core]system.runtime.compilerservices.callsite, object, int32>>::create(class [system.core]system.runtime.compilerservices.callsitebinder) l_004e: stsfld class [system.core]system.runtime.compilerservices.callsite`1<class [mscorlib]system.action`3<class [system.core]system.runtime.compilerservices.callsite, object, int32>> consoleapplication1.worker/<dosomething>o__sitecontainer0::<>p__site1 l_0053: br l_0058 l_0058: ldsfld class [system.core]system.runtime.compilerservices.callsite`1<class [mscorlib]system.action`3<class [system.core]system.runtime.compilerservices.callsite, object, int32>> consoleapplication1.worker/<dosomething>o__sitecontainer0::<>p__site1 l_005d: ldfld !0 [system.core]system.runtime.compilerservices.callsite`1<class [mscorlib]system.action`3<class [system.core]system.runtime.compilerservices.callsite, object, int32>>::target l_0062: ldsfld class [system.core]system.runtime.compilerservices.callsite`1<class [mscorlib]system.action`3<class [system.core]system.runtime.compilerservices.callsite, object, int32>> consoleapplication1.worker/<dosomething>o__sitecontainer0::<>p__site1 l_0067: ldarg.1 l_0068: ldc.i4.s 12 l_006a: callvirt instance void [mscorlib]system.action`3<class [system.core]system.runtime.compilerservices.callsite, object, int32>::invoke(!0, !1, !2) l_006f: nop l_0070: ret }
Comments
Post a Comment