Search code examples
c#dynamiccasting

C# - Accept IEnumerable of any type as parameter


i have this constructor which was supposed to accept any IEnumerable of any type, and try to convert the values to the desired type

public ChartData(IEnumerable<dynamic> labels, IEnumerable<dynamic> values)
            {
                this.values = values.Select(x=>(float)Convert.ToString(x));
                this.labels = labels.Select(x=>(string)Convert.ToString(x));
            }

when i call this constructor i can pass ienumerables of the type string, but not int or float how can i make a constructor that will accept ienumerables of any type without making tons of overloads?


Solution

  • If you don't care about the type use non-generic version IEnumerable(which is base interface for IEnumerble<T>):

    public ChartData(IEnumerable labels, IEnumerable values)
    {
          // x is of type Object for both lines.
          this.values = values.Select(x=>(float)Convert.ToSingle(x));
          this.labels = labels.Select(x=>(string)Convert.ToString(x));
    }
    

    Note that

    • you lose all type safety - someone can easily pass list of files or some other random types as either of arguments
    • in general generics version is preferable if you deal with value types due to boxing cost. Fortunately in your case you need boxed value anyway or Convert.

    Personally I'd only accept IEnumerable<float> (or maybe double) and IEnumerable<String> as arguments - caller of this method will have more knowledge to pick desired fields/conversion than my code trying to guess the type they passed in. If some "any numeric type" would be a desired input I'd check Is there a constraint that restricts my generic method to numeric types? and implement all variant instead of falling back to runtime reflection with dynamic or lack of type safety with non-generic version.