Click here to Skip to main content
15,847,902 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hello, I got another weird issue in C# where the method "Count" of IEnumerable and the "Count" property of List raises an InvalidCastException. I may not be very clear about this issue so I'll show you the piece of code where the exception is raised:
C#
int count = items.Count(); // The method raises an InvalidCastException
.
Note: the items are Int64 (long).

What I have tried:

I googled my problem but for the other people it only raises because they are trying to cast from a type to another but for me it's only because of the Count method of IEnumerable and Count property of List.
I also tried converting the IEnumerable to a List then using its Count property:
C#
int count = items.ToList().Count // The property now also raises an InvalidCastException
the first time it worked but then it didn't work anymore.
I think I have no other choices than iterating over the IEnumerable. If you have a better solution than iterating all over the IEnumerable just to get how many elements are in the IEnumerable, this would be very nice!
Thanks for your attention to this problem!
Posted
Updated 11-Jun-23 23:45pm
v2
Comments
Le lance Flamer 10-Jun-23 3:49am    
I just found out than in the code of the Count() method it cast from IEnumerable to ICollection.
(ICollection<tsource> collection = source as ICollection<tsource>;) so this may be the problem of InvalidCastException.

That is correct, IEnumerable does not support Count property. IEnumerable only supports iteration of collections.

You do need to cast to a type that supports that property. The ICollection<T> Interface (System.Collections.Generic) | Microsoft Learn[^] supports the Count property.

Here is an example:
C#
IEnumerable <string> names = new List<String>()
{
    "John",
    "Paul",
    "Ringo",
    "George"
};

ICollection<string> collection = names as ICollection<string>;

int count = collection.Count;

Console.WriteLine(count);

The output is: 4
 
Share this answer
 
Comments
OriginalGriff 10-Jun-23 4:04am    
Erm ... are you sure: Reference Source[^]
Graeme_Grant 10-Jun-23 4:17am    
Depends on how he initialized his collection. The List collection has the following interfaces:

public class List<T>
    : ICollection<T>,
      IEnumerable<T>,
      IEnumerable,
      IList<T>,
      IReadOnlyCollection<T>,
      IReadOnlyList<T>,
      ICollection,
      IList
{
}
Le lance Flamer 10-Jun-23 4:06am    
Thank you for your help, so I did what you did but when I now use the Count property of the collection it throws a NullReferenceException. I put it in an if condition to check if it's null or not but it is not null.
Graeme_Grant 10-Jun-23 4:10am    
You have not shown us what the Items collection is. Please update your question.
Le lance Flamer 10-Jun-23 4:25am    
Just did it. The items are Int64 which shouldn't be a problem, right?
That's not what I get:
C#
List<string> itemsAsList = new List<string> { "one", "two", "three" };
IEnumerable<string> items = itemsAsList;
int count = items.Count();
Console.WriteLine(count);
count = items.ToList().Count;
Console.WriteLine(count);
count = items.ToList().Count();
Console.WriteLine(count);
count = itemsAsList.ToList().Count;
Console.WriteLine(count);
count = itemsAsList.ToList().Count();
Console.WriteLine(count);
count = itemsAsList.Count;
Console.WriteLine(count);
count = itemsAsList.Count();
Console.WriteLine(count);
Gives me
Results
3
3
3
3
3
3
3
Which is what I expected.
So I'd suggest that the first thing you want to do is use the debugger to find out exactly what items contains - I don't think it's what you think it is.
 
Share this answer
 
v2
Comments
Le lance Flamer 10-Jun-23 4:08am    
Hello, this is what I expect it to return but it throws an InvalidCastException which shouldn't be the case. In every other C# projects I've done this never happened.
Thanks for your help!
OriginalGriff 10-Jun-23 4:10am    
That's why I think you need to check items with the debugger. You know how to do that, don't you?
Le lance Flamer 10-Jun-23 4:18am    
Yes, the items are Int64, and they aren't null. I only have a few values. But I fixed the problem by changing the method parameter type from IEnumerable to List. But it still doesn't makes sense that even by converting to List from the IEnumerable it throws this exceptions, but by simply replacing IEnumerable by List in the method parameters it worked. I'll leave this question open because I'll need to use IEnumerable for items
OriginalGriff 10-Jun-23 4:43am    
No, use the debugger to look at the variable called items - it will tell you exactly what it contains. That isn't the same as the content of a collection: in my example, items and itemsAsList are variables which reference a collection - the collection itself contains three strings. I suspect that your variable doesn't contain the right collection but we can't see that code. Even if we could, it needs your code running under the debugger to absolutely confirm the content. You do know how to use the debugger, don't you?
OriginalGriff 10-Jun-23 4:14am    
I notice your reply to Graeme says a "null reference" occurred when you tried to use as to convert it to an ICollection - it does that if the item being converted does not implement the ICollection interface - as returns null in that case.
You definitely need to check items and see exactly what it is.
The only way Count() or ToList() will throw an InvalidCastException is if you have a source list which contains values of different types, and you've used Cast<SomeType> to treat it as a list of a single type. *
C#
List<object> source = new List<object>
{
    42,
    42L,
    42F,
    42M,
    "42",
};

IEnumerable<long> items = source.Cast<long>();
items.Count(); // throws InvalidCastException
items.ToList(); // throws InvalidCastException

foreach (long value in items) // throws InvalidCastException
{
    ...
}
Demo[^]

This is clearly described in the documentation of the Cast method:
Exceptions
InvalidCastException
An element in the sequence cannot be cast to type TResult.

You can either filter the list to only include those items which are of the specified type:
C#
IEnumerable<long> items = source.OfType<long>();
Or, if you're certain that all of the types in the list can be converted to the specified type, use a projection:
C#
IEnumerable<long> items = source.Select(i => Convert.ToInt64(i));


* NB: This doesn't apply if the values all inherit from a base class and you use Cast<BaseClass>, or they all implement an interface and you use Cast<TheInterface>.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900