c# - Avoid excessive type-checking in generic methods? -
my question concerns type-checking in chain of generic methods. let's have extension method attempts convert byte array int, decimal, string, or datetime.
public static t read<t>(this bytecontainer ba, int size, string format) t : struct, iconvertible { var s = string.concat(ba.bytes.select(b => b.tostring(format)).toarray()); var magic = fromstring<t>(s); return (t)convert.changetype(magic, typeof(t)); }
this calls method called fromstring translates concatenated string specific type. unfortunately, business logic dependent on type t. end megalithic if-else block:
private static t fromstring<t>(string s) t : struct { if (typeof(t).equals(typeof(decimal))) { var x = (decimal)system.convert.toint32(s) / 100; return (t)convert.changetype(x, typeof(t)); } if (typeof(t).equals(typeof(int))) { var x = system.convert.toint32(s); return (t)convert.changetype(x, typeof(t)); } if (typeof(t).equals(typeof(datetime))) ... etc ... }
at point, prefer multiple methods same name , different return types, along lines of this:
// <wishfulthinking> private static decimal fromstring<t>(string s) { return (decimal)system.convert.toint32(s) / 100; } private static int fromstring<t>(string s) { return system.convert.toint32(s); } // </wishfulthinking>
... realize not valid, t can't constrained specific type, , without it, of methods have same conflicting signature.
is there feasible way implement fromstring without excessive type-checking? or might there better way approach problem altogether?
or might there better way approach problem altogether?
sure, there one: can make each converter lambda, make dictionary of them, , use them conversion, this:
private static idictionary<type,func<string,object>> converters = new dictionary<type,func<string,object>> { {typeof(int), s => convert.changetype(system.convert.toint32(s), typeof(int))} , {typeof(decimal), s => convert.changetype((decimal)system.convert.toint32(s) / 100, typeof(decimal))} , ... // , on }; public static t read<t>(this bytecontainer ba, int size, string format) t : struct, iconvertible { func<string,object> converter; if (!converters.trygetvalue(typeof(t), out converter)) { throw new argumentexception("unsupported type: "+typeof(t)); } var s = string.concat(ba.bytes.select(b => b.tostring(format)).toarray()); return (t)converter(s); }
Comments
Post a Comment