Help needed to convert function to a generic function
-
I have a function that a function that takes in a string like "1,2,3,4324,3423". I need to return an array of a type that I specifiy using that string so in this case it would return an array of ints or shorts etc like { 1, 2, 3, 4324, 3423 }. The code I wrote to do this is below ...
usage: int[] myInts = (int[])CommaSeparatedStringToIEnumerable("1,2,3,4324,3423", typeof(int)); public static IEnumerable CommaSeparatedStringToIEnumerable(string str, Type destinationType) { List list = new List(str.Split(',')); list.RemoveAll(delegate(string s) { return s.Trim().Length == 0 ;}); IEnumerable output; if (destinationType == typeof(int)) output = list.ConvertAll(delegate(string s) { return Convert.ToInt32(s.Trim()); }).ToArray(); else if (destinationType == typeof(short)) output = list.ConvertAll(delegate(string s) { return Convert.ToInt16(s.Trim()); }).ToArray(); else if (destinationType == typeof(byte)) output = list.ConvertAll(delegate(string s) { return Convert.ToByte(s.Trim()); }).ToArray(); else if (destinationType == typeof(bool)) output = list.ConvertAll(delegate(string s) { return Convert.ToBoolean(s.Trim()); }).ToArray(); else if (destinationType == typeof(string)) output = list.ConvertAll(delegate(string s) { return s.Trim(); }).ToArray(); else throw new NotSupportedException("Type not supported."); return output; }
I can't help thinking that this could be acheived using a generic function like public static T[] CommaSeparatedStringToArray(string str) but I've been round the houses trying to do this. Any ideas, good articles would be appreciated.Jim
-
I have a function that a function that takes in a string like "1,2,3,4324,3423". I need to return an array of a type that I specifiy using that string so in this case it would return an array of ints or shorts etc like { 1, 2, 3, 4324, 3423 }. The code I wrote to do this is below ...
usage: int[] myInts = (int[])CommaSeparatedStringToIEnumerable("1,2,3,4324,3423", typeof(int)); public static IEnumerable CommaSeparatedStringToIEnumerable(string str, Type destinationType) { List list = new List(str.Split(',')); list.RemoveAll(delegate(string s) { return s.Trim().Length == 0 ;}); IEnumerable output; if (destinationType == typeof(int)) output = list.ConvertAll(delegate(string s) { return Convert.ToInt32(s.Trim()); }).ToArray(); else if (destinationType == typeof(short)) output = list.ConvertAll(delegate(string s) { return Convert.ToInt16(s.Trim()); }).ToArray(); else if (destinationType == typeof(byte)) output = list.ConvertAll(delegate(string s) { return Convert.ToByte(s.Trim()); }).ToArray(); else if (destinationType == typeof(bool)) output = list.ConvertAll(delegate(string s) { return Convert.ToBoolean(s.Trim()); }).ToArray(); else if (destinationType == typeof(string)) output = list.ConvertAll(delegate(string s) { return s.Trim(); }).ToArray(); else throw new NotSupportedException("Type not supported."); return output; }
I can't help thinking that this could be acheived using a generic function like public static T[] CommaSeparatedStringToArray(string str) but I've been round the houses trying to do this. Any ideas, good articles would be appreciated.Jim
static T[] CommaSeparatedStringToIEnumerable(string values) { List list = new List(values.Split(',')); List ret = new List(); foreach(string value in list) ret.Add(ConvertValue(value)); return ret.ToArray(); } static T ConvertValue(object value) { Converter convert = new Converter(delegate(object val) { return (T)val; }); switch(typeof(T).ToString()) { case "System.Int16": case "System.Int32": int RetInt; if(int.TryParse(value.ToString(), out RetInt)) return convert(RetInt); break; case "System.Single": float RetFloat; if(float.TryParse(value.ToString(), out RetFloat)) return convert(RetFloat); break; case "System.Double": double RetDouble; if(double.TryParse(value.ToString(), out RetDouble)) return convert(RetDouble); break; default: return convert(value); } return convert(value); }
only two letters away from being an asset
-
static T[] CommaSeparatedStringToIEnumerable(string values) { List list = new List(values.Split(',')); List ret = new List(); foreach(string value in list) ret.Add(ConvertValue(value)); return ret.ToArray(); } static T ConvertValue(object value) { Converter convert = new Converter(delegate(object val) { return (T)val; }); switch(typeof(T).ToString()) { case "System.Int16": case "System.Int32": int RetInt; if(int.TryParse(value.ToString(), out RetInt)) return convert(RetInt); break; case "System.Single": float RetFloat; if(float.TryParse(value.ToString(), out RetFloat)) return convert(RetFloat); break; case "System.Double": double RetDouble; if(double.TryParse(value.ToString(), out RetDouble)) return convert(RetDouble); break; default: return convert(value); } return convert(value); }
only two letters away from being an asset
Many thanks Mark, that works a treat!! :)
Jim
-
I have a function that a function that takes in a string like "1,2,3,4324,3423". I need to return an array of a type that I specifiy using that string so in this case it would return an array of ints or shorts etc like { 1, 2, 3, 4324, 3423 }. The code I wrote to do this is below ...
usage: int[] myInts = (int[])CommaSeparatedStringToIEnumerable("1,2,3,4324,3423", typeof(int)); public static IEnumerable CommaSeparatedStringToIEnumerable(string str, Type destinationType) { List list = new List(str.Split(',')); list.RemoveAll(delegate(string s) { return s.Trim().Length == 0 ;}); IEnumerable output; if (destinationType == typeof(int)) output = list.ConvertAll(delegate(string s) { return Convert.ToInt32(s.Trim()); }).ToArray(); else if (destinationType == typeof(short)) output = list.ConvertAll(delegate(string s) { return Convert.ToInt16(s.Trim()); }).ToArray(); else if (destinationType == typeof(byte)) output = list.ConvertAll(delegate(string s) { return Convert.ToByte(s.Trim()); }).ToArray(); else if (destinationType == typeof(bool)) output = list.ConvertAll(delegate(string s) { return Convert.ToBoolean(s.Trim()); }).ToArray(); else if (destinationType == typeof(string)) output = list.ConvertAll(delegate(string s) { return s.Trim(); }).ToArray(); else throw new NotSupportedException("Type not supported."); return output; }
I can't help thinking that this could be acheived using a generic function like public static T[] CommaSeparatedStringToArray(string str) but I've been round the houses trying to do this. Any ideas, good articles would be appreciated.Jim
Here's an elegant way to do it with using C# 2's yield iterators, generics, and delegate inference:
public static IEnumerable<T> CommaSeperatedToIEnumerable<T>(string commaSeperatedValues, Converter<string, T> converter)
{
foreach (string value in commaSeperatedValues.Split(','))
{
yield return converter(value);
}
}Consuming code would look like this:
IEnumerable<int> myInts = CommaSeperatedSTringToIEnumerable<int>("1,2,3,4324,3423", int.Parse);
Powerful, fun, elegant, works on all types of T. :) Pretty efficient too, since the results will be computed only as you ask for the values in a foreach.
Tech, life, family, faith: Give me a visit. I'm currently blogging about: Funny Love The apostle Paul, modernly speaking: Epistles of Paul Judah Himango
-
Here's an elegant way to do it with using C# 2's yield iterators, generics, and delegate inference:
public static IEnumerable<T> CommaSeperatedToIEnumerable<T>(string commaSeperatedValues, Converter<string, T> converter)
{
foreach (string value in commaSeperatedValues.Split(','))
{
yield return converter(value);
}
}Consuming code would look like this:
IEnumerable<int> myInts = CommaSeperatedSTringToIEnumerable<int>("1,2,3,4324,3423", int.Parse);
Powerful, fun, elegant, works on all types of T. :) Pretty efficient too, since the results will be computed only as you ask for the values in a foreach.
Tech, life, family, faith: Give me a visit. I'm currently blogging about: Funny Love The apostle Paul, modernly speaking: Epistles of Paul Judah Himango
Thanks Judah that is quite cool. I'm really enjoying learning the new language features in .NET 2.0!
Jim
-
Here's an elegant way to do it with using C# 2's yield iterators, generics, and delegate inference:
public static IEnumerable<T> CommaSeperatedToIEnumerable<T>(string commaSeperatedValues, Converter<string, T> converter)
{
foreach (string value in commaSeperatedValues.Split(','))
{
yield return converter(value);
}
}Consuming code would look like this:
IEnumerable<int> myInts = CommaSeperatedSTringToIEnumerable<int>("1,2,3,4324,3423", int.Parse);
Powerful, fun, elegant, works on all types of T. :) Pretty efficient too, since the results will be computed only as you ask for the values in a foreach.
Tech, life, family, faith: Give me a visit. I'm currently blogging about: Funny Love The apostle Paul, modernly speaking: Epistles of Paul Judah Himango
Damn, I always forget about the yield keyword, then get reminded, then forget all about it again.
only two letters away from being an asset
-
Damn, I always forget about the yield keyword, then get reminded, then forget all about it again.
only two letters away from being an asset
The real trick of the above solution, of course, is the
Converter<int, T>
delegate; without it, we'd have to resort back to the a bunch of if/elses using hard coded types. That's no fun. The yield stuff is really nice. LINQ uses it heavily; you can imagine the LINQ 'where' keyword actually uses a function underneath the hood:public static IEnumerable<T> Where<T>(IEnumerable<T> items, Predicate<T> criteria)
{
foreach(T item in items)
{
if(criteria(item)) yield return item;
}
}Of course, with current C# 2 syntax, consuming this is a little ugly:
int[] ints = {5, 10, 15, 20};
IEnumerable evenIntegers = Linq.Where(ints, delegate(int i) { return i % 2 == 0; });C# 3 makes this a little better with lambda expressions:
IEnumerable evenIntegers = Linq.Where(ints, i => i % 2 == 0);
C# 3 improves it further by extension methods: taking static methods like our Where method and making them appear to be instance methods:
IEnumerable evenIntegers = ints.Where(i => i % 2 == 0);
Better, but still a little odd. The "language integrated" part of LINQ adds some new keywords to C# 3:
IEnumerable evenIntegers = from ints where i % 2 == 0 select i;
Pretty cool stuff; builds heavily on C# 2's delegate inference, anonymous methods, and yielding iterators. And lastly, it's rather laborious to type IEnumerable<int> all over:
var evenIntegers = from ints where i % 2 == 0 select i;
Tech, life, family, faith: Give me a visit. I'm currently blogging about: Funny Love The apostle Paul, modernly speaking: Epistles of Paul Judah Himango
-
I have a function that a function that takes in a string like "1,2,3,4324,3423". I need to return an array of a type that I specifiy using that string so in this case it would return an array of ints or shorts etc like { 1, 2, 3, 4324, 3423 }. The code I wrote to do this is below ...
usage: int[] myInts = (int[])CommaSeparatedStringToIEnumerable("1,2,3,4324,3423", typeof(int)); public static IEnumerable CommaSeparatedStringToIEnumerable(string str, Type destinationType) { List list = new List(str.Split(',')); list.RemoveAll(delegate(string s) { return s.Trim().Length == 0 ;}); IEnumerable output; if (destinationType == typeof(int)) output = list.ConvertAll(delegate(string s) { return Convert.ToInt32(s.Trim()); }).ToArray(); else if (destinationType == typeof(short)) output = list.ConvertAll(delegate(string s) { return Convert.ToInt16(s.Trim()); }).ToArray(); else if (destinationType == typeof(byte)) output = list.ConvertAll(delegate(string s) { return Convert.ToByte(s.Trim()); }).ToArray(); else if (destinationType == typeof(bool)) output = list.ConvertAll(delegate(string s) { return Convert.ToBoolean(s.Trim()); }).ToArray(); else if (destinationType == typeof(string)) output = list.ConvertAll(delegate(string s) { return s.Trim(); }).ToArray(); else throw new NotSupportedException("Type not supported."); return output; }
I can't help thinking that this could be acheived using a generic function like public static T[] CommaSeparatedStringToArray(string str) but I've been round the houses trying to do this. Any ideas, good articles would be appreciated.Jim
Hi the following code use reflection in order to convert string items to value types using the static function TryParse. using System; using System.Collections.Generic; using System.Reflection; namespace CMDLineTest { class Program { static List CommaSeparatedStringToIEnumerable(string s) { List values = new List(); Type targetConversionType = typeof(T); if (targetConversionType.IsValueType) { Type targetConversionTypeOutParamType = Type.GetType(targetConversionType.FullName + @"&"); if(targetConversionTypeOutParamType == null) throw new Exception(""); MethodInfo tryParseMethodInfo = targetConversionType.GetMethod("TryParse", new Type[] { typeof(string), targetConversionTypeOutParamType }); if(tryParseMethodInfo != null) { string[] stringsToConvert = s.Split(','); T item = default(T); object[] methodParams = new object[2]; foreach (string str in stringsToConvert) { methodParams[0] = str; methodParams[1] = item; if (((bool)tryParseMethodInfo.Invoke(null, methodParams)) == true) values.Add((T)methodParams[1]); } } } return values; } static void Main(string[] args) { List intList = CommaSeparatedStringToIEnumerable("1,2,3,4,5"); foreach (int item in intList) Console.WriteLine(item); } } }