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

Popular posts from this blog

c# - Operator '==' incompatible with operand types 'Guid' and 'Guid' using DynamicExpression.ParseLambda<T, bool> -