Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Help needed to convert function to a generic function

Help needed to convert function to a generic function

Scheduled Pinned Locked Moved C#
data-structureshelp
8 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    Jim Taylor
    wrote on last edited by
    #1

    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

    N J N 3 Replies Last reply
    0
    • J Jim Taylor

      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

      N Offline
      N Offline
      Not Active
      wrote on last edited by
      #2

      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

      J 1 Reply Last reply
      0
      • N Not Active

        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

        J Offline
        J Offline
        Jim Taylor
        wrote on last edited by
        #3

        Many thanks Mark, that works a treat!! :)

        Jim

        1 Reply Last reply
        0
        • J Jim Taylor

          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

          J Offline
          J Offline
          Judah Gabriel Himango
          wrote on last edited by
          #4

          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

          J N 2 Replies Last reply
          0
          • J Judah Gabriel 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

            J Offline
            J Offline
            Jim Taylor
            wrote on last edited by
            #5

            Thanks Judah that is quite cool. I'm really enjoying learning the new language features in .NET 2.0!

            Jim

            1 Reply Last reply
            0
            • J Judah Gabriel 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

              N Offline
              N Offline
              Not Active
              wrote on last edited by
              #6

              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

              J 1 Reply Last reply
              0
              • N Not Active

                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

                J Offline
                J Offline
                Judah Gabriel Himango
                wrote on last edited by
                #7

                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

                1 Reply Last reply
                0
                • J Jim Taylor

                  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

                  N Offline
                  N Offline
                  Nissim Salomon
                  wrote on last edited by
                  #8

                  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); } } }

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups