Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting string to IEnumerable<object>

I have propertyValue which is an object passed into my function.

I can assume that this is an IEnumerable of some kind, however due to the interface contract I must accept it as an object rather than directly as an IEnumerable.

When I try to cast my value to an IEnumerable<object>, so that I can get the length, I get an InvalidCastException.

var length = ((IEnumerable<object>) propertyValue).Cast<object>().Count();

I get the following exception:

System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Collections.Generic.IEnumerable`1[System.Object]'.

like image 489
James Monger Avatar asked Dec 22 '15 12:12

James Monger


3 Answers

The IEnumerable<T> interface is covariant, but covariance doesn't work with value types. Casting a value type to reference type changes representation - the value needs to be boxed and the reference to the boxed value is returned. Casting reference types doesn't change representation - it's still the same reference, referencing the same object.

string is an IEnumerable<char>, so it cannot be cast to IEnumerable<object>.

As mentioned in other answers, the solution is to cast to non-generic IEnumerable.

var length = ((IEnumerable) propertyValue).Cast<object>().Count();
like image 113
Jakub Lortz Avatar answered Sep 29 '22 16:09

Jakub Lortz


I have fixed the issue by simply casting to IEnumerable rather than casting to IEnumerable<object>.

var length = ((IEnumerable) propertyValue).Cast<object>().Count();
like image 24
James Monger Avatar answered Sep 29 '22 18:09

James Monger


String implements the IEnumerable<char> interface, you can cast it to this interface

var length = ((IEnumerable<char>) propertyValue).Count();

For unknown types of collection you can cast it to IEnumerable and next enumerate values manually with your own extension method.

static class EnumerableExtensions
{
    public static int Count(this IEnumerable source)
    {
        int res = 0;

        foreach (var item in source)
            res++;

        return res;
    }
}

var collection = propertyValue as IEnumerable;
if(collection != null)
{
    var length = collection.Count();
}

Using Cast() method will cause to boxing of value types and it may have an performance issues for big collections.

like image 38
Vadim Martynov Avatar answered Sep 29 '22 18:09

Vadim Martynov