Partial generic type inference possible in C#? -
i working on rewriting fluent interface ioc class library, , when refactored code in order share common functionality through base class, hit upon snag.
note: want do, not have do. if have make different syntax, will, if has idea on how make code compile way want it, welcome.
i want extension methods available specific base-class, , these methods should generic, 1 generic type, related argument method, methods should return specific type related particular descendant they're invoked upon.
better code example above description methinks.
here's simple , complete example of doesn't work:
using system; namespace consoleapplication16 { public class parameterizedregistrationbase { } public class concretetyperegistration : parameterizedregistrationbase { public void somethingconcrete() { } } public class delegateregistration : parameterizedregistrationbase { public void somethingdelegated() { } } public static class extensions { public static parameterizedregistrationbase parameter<t>( parameterizedregistrationbase p, string name, t value) { return p; } } class program { static void main(string[] args) { concretetyperegistration ct = new concretetyperegistration(); ct .parameter<int>("age", 20) .somethingconcrete(); // <-- not available delegateregistration del = new delegateregistration(); del .parameter<int>("age", 20) .somethingdelegated(); // <-- neither } } } if compile this, you'll get:
'consoleapplication16.parameterizedregistrationbase' not contain definition 'somethingconcrete' , no extension method 'somethingconcrete'... 'consoleapplication16.parameterizedregistrationbase' not contain definition 'somethingdelegated' , no extension method 'somethingdelegated'... what want extension method (parameter<t>) able invoked on both concretetyperegistration , delegateregistration, , in both cases return type should match type extension invoked on.
the problem follows:
i write:
ct.parameter<string>("name", "lasse") ^------^ notice 1 generic argument but parameter<t> returns object of same type invoked on, means:
ct.parameter<string>("name", "lasse").somethingconcrete(); ^ ^-------+-------^ | | +---------------------------------------------+ .somethingconcrete comes object in "ct" in case of type concretetyperegistration is there way can trick compiler making leap me?
if add 2 generic type arguments parameter method, type inference forces me either provide both, or none, means this:
public static treg parameter<treg, t>( treg p, string name, t value) treg : parameterizedregistrationbase gives me this:
using generic method 'consoleapplication16.extensions.parameter<treg,t>(treg, string, t)' requires 2 type arguments using generic method 'consoleapplication16.extensions.parameter<treg,t>(treg, string, t)' requires 2 type arguments which bad.
i can restructure classes, or make methods non-extension-methods introducing them hierarchy, question if can avoid having duplicate methods 2 descendants, , in way declare them once, base class.
let me rephrase that. there way change classes in first code example above, syntax in main-method can kept, without duplicating methods in question?
the code have compatible both c# 3.0 , 4.0.
edit: reason i'd rather not leave both generic type arguments inference services, want specify parameter value constructor parameter of 1 type, pass in value descendant. moment, matching of specified argument values , correct constructor call done using both name , type of argument.
let me give example:
servicecontainerbuilder.register<isomeservice>(r => r .from(f => f.concretetype<fileservice>(ct => ct .parameter<stream>("source", new filestream(...))))); ^--+---^ ^---+----^ | | | +- has descendant of stream | +- has match constructor of fileservice if leave both type inference, parameter type filestream, not stream.
if have 2 specific types of registration (which seems case in question), implement 2 extension methods:
public static delegateregistration parameter<t>( delegateregistration p, string name, t value); public static concretetyperegistration parameter<t>( concretetyperegistration p, string name, t value); then wouldn't need specify type argument, type inference work in example mentioned. note can implement both of extension methods delegation single generic extension method 2 type parameters (the 1 in question).
in general, c# doesn't support o.foo<int, ?>(..) infer second type parameter (it nice feature - f# has , it's quite useful :-)). implement workaround allow write (basically, separating call 2 method calls, 2 places type inferrence can applied):
footrick<int>().apply(); // apply generic method here pseudo-code demonstrate structure:
// in original object fooimmediatewrapper<t> footrick<t>() { return new fooimmediatewrapper<t> { invokeon = this; } } // in fooimmediatewrapper<t> class (...) apply<r>(arguments) { this.invokeon.foo<t, r>(arguments); }
Comments
Post a Comment