How to call type conversion operator in C# generic class? -


it seems cannot call type conversion operator easily in c# generic class. here code. why?

t006 archive our target.

using system; using system.collections.generic; using system.text; using system.diagnostics; using system.reflection; using system.linq;  namespace consoleapplication1 {     class vec<t, t2> : list<t> t : class     {         public vec(ienumerable<t2> other)         {             //converter<t2, t> cvt = (v) => (t)v; // t004 failed, try defined function dynamicly, cannot compile, too.              // t006 pass, client happy, not happy, anyway passed, performance may not happy.             var conversionoperator = typeof(t).getmethods(bindingflags.static | bindingflags.public)                                     .where(m => m.name == "op_explicit" || m.name == "op_implicit")                                     .where(m => m.returntype == typeof(t))                                     .where(m => m.getparameters().length == 1 && m.getparameters()[0].parametertype == typeof(t2))                                     .firstordefault();             func<t2, t> cvt = (obj) =>             {                 if (conversionoperator != null)                     return (t)conversionoperator.invoke(null, new object[] { obj });                 else                     return default(t);             };              foreach (t2 item in other)             {                 //add((t)item);         // t001 failed, line cannot compile                 //add(item t);       // t002 failed, line alwasy return null. //  http://msdn.microsoft.com/en-us/library/vstudio/cscsdfbt.aspx                 //add((t)(object)item); // t003 failed, pass compile, throw exception @ runtime.                 add(cvt(item));         // t006 pass.             }         }          // t005 pass, clients code not happy.         public vec(converter<t2, t> cvt, ienumerable<t2> other)         {             foreach (t2 item in other)             {                 add(cvt(item));             }          }     }      class xxx     {         public int foo = 22;         static public explicit operator xxx(yyy other)         {             xxx me = new xxx();             me.foo = (int)other.foo;             return me;         }     }      class yyy     {         public float foo = 11;     }        class program     {         static void main(string[] args)         {             yyy[] = new yyy[2];             (int = 0; < from.length; i++)             {                 from[i] = new yyy();             }              xxx x = (xxx)from[0];              vec<xxx, yyy> coll = new vec<xxx, yyy>(from);              // not happy, requires user have strong c# skill;             //vec<xxx, yyy> coll = new vec<xxx, yyy>((v) => (xxx)v, from);              foreach (var item in coll)             {                 debug.print("value {0}", item.foo);             }          }     }  } 

the compiler error t001 is: cannot convert type 't2' 't'

if need have custom implicit/explicit conversion operators run, casting to/from object (or performing as cast) skip them because information known @ compile-time when performing runtime cast.

the way know of, through general-use generic method such posted, leverage dynamic lookup @ runtime see if there conversion operators defined , call them:

return (t2)(dynamic)obj; 

quick example:

public class class1 {      public static implicit operator class1(class2 class2)     {         console.writeline("implicit conversion class2 class1");         return new class1();     }      public static implicit operator class2(class1 class1)     {     console.writeline("implicit conversion class1 class2");         return new class2();     } }  public class class2 {  }  public static t2 convert<t1, t2>(t1 obj) {     return (t2)(dynamic)obj; }  var class1 = new class1(); var class2 = convert<class1, class2>(class1); //outputs: implicit conversion class1 class2 

be aware though, using reflection , doing significant work @ runtime, thoroughly test , make sure performance still acceptable.

edit: since not have access dynamic language runtime, can write own conversion operator lookups reflection:

public static t2 convert<t1, t2>(t1 obj) {     var conversionoperator = typeof(t1).getmethods(bindingflags.static | bindingflags.public)     .where(m => m.name == "op_explicit" || m.name == "op_implicit")     .where(m => m.returntype == typeof(t2))     .where(m => m.getparameters().length == 1 && m.getparameters()[0].parametertype == typeof(t1))     .firstordefault();      if (conversionoperator != null)         return (t2)conversionoperator.invoke(null, new object[]{obj});      throw new exception("no conversion operator found"); } 

you may need tweak code (perhaps attempt traditional casting if no operators found), , i'm not sure if can guarantee work every time. don't know if there corner cases or platform quirks handle. not mention pretty slow reflection. introduce quick caching mechanism o(1) lookup dictionary or can store each conversion operator they're found each type combination.


Comments