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