Why does the following DisplayContents not work(wont compile) for an ArrayList as it inherits form IEnumerable)
public class Program
{
static void Main(string[] args)
{
List<int> l = new List<int>(){1,2,3};
DisplayContents(l);
string[] l2 = new string[] {"ss", "ee"};
DisplayContents(l2);
ArrayList l3 = new ArrayList() { "ss", "ee" };
DisplayContents < ArrayList>(l3);
Console.ReadLine();
}
public static void DisplayContents<T>(IEnumerable<T> collection)
{
foreach (var _item in collection)
{
Console.WriteLine(_item);
}
}
}
ArrayList implements IEnumerable, but not the generic IEnumerable<T>. This is to be expected, since ArrayList is neither generic nor bound to any specific type.
You need to change the parameter type of your DisplayContents method from IEnumerable<T> to IEnumerable and remove its type parameter. The items of your collection are passed to Console.WriteLine, which can accept any object.
public static void DisplayContents(IEnumerable collection)
{
foreach (var _item in collection)
{
Console.WriteLine(_item);
}
}
ArrayList at all since it is unnecessary. Use List<object> if you really need to, and the answer to that is probably "no" - Ed S. 2012-04-04 18:31
IEnumerable<T> for their specific type. ArrayList is an outdated type, there was no reason to add another interface to it when generics were introduced - Ed S. 2012-04-04 18:34
string[] implements IEnumerable<string> (as well as ICollection<string> and IList<string>) - Douglas 2012-04-04 18:34
ArrayList should be avoided in almost all circumstances - Douglas 2012-04-04 18:35
MailItem and DocumentItem objects from the same Folder.Items collection, whose types have no common ancestor despite sharing most properties. The issue was only alleviated with .NET 4’s dynamic keyword - Douglas 2012-04-04 18:41
ArrayList. I’m not aware of the advantages a List<object> would have over it - Douglas 2012-04-04 18:43
IEnumerable<T> :) But yeah, that's what I was saying; you will/should use an ArrayList only when forced to by an API that you do not control - Ed S. 2012-04-04 18:57
IEnumerable<T> detail. Which is important since IEnumerable<T> allows you to leverage LINQ (through the <code>Enumerable</code> extension methods) - Douglas 2012-04-04 19:08
Well, a quick check of the docs tells me that ArrayList does not implement IEnumerable<T>, but instead implements IEnumerable, which makes sense as ArrayList is a vestigial artifact from the days before generics and has few real uses today.
There's really no reason to use ArrayList at all. You can at least use a List<object>, but what problem does that solve? Unless you absolutely need to have a collection of random types that do not / cannot implement a common interface and cannot be grouped into a new type then use a more specific generic parameter.
ArrayList implements IEnumerable, but not generic IEnumerable<T>
UPDATE: This will work:
public static void DisplayContents(IEnumerable collection)
{
foreach (var _item in collection)
Console.WriteLine(_item);
}
ArrayList l3 = new ArrayList() { "ss", "ee" };
DisplayContents<ArrayList>(l3);
Look at your code. You're passing DisplayContents() a list of strings but you're telling it to expect a list of ArrayLists.
You probably meant to just call DisplayContents<string>(l3), but as everyone else has already mentioned, that won't work because ArrayList does not implement the generic IEnumerable<T>, it only implements IEnumerable.
You could instead call
DisplayContents<string>((string[])l3.ToArray(typeof(string)));
This will work because string[] implements IEnumerable<string>.
How about an extension method?
/// <summary>
/// Projects any <see cref="IEnumerable"/>, e.g. an <see cref="ArrayList"/>
/// to an generic <see cref="IEnumerable{T}"/>.
/// </summary>
/// <typeparam name="T">The type to project to.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="map">The mapping function.</param>
/// <returns>A sequence of <typeparamref name="T"/>.</returns>
public static IEnumerable<T> Select<T>(this IEnumerable source, Func<object, T> map)
{
foreach(var item in source)
{
yield return map(item);
}
}
If you change the calling line to this, it works:
DisplayContents(l3.ToArray());