views:

82

answers:

3

I'm still learning some of this c# stuff, and I couldn't find an answer to this question. Assuming that I have a list of MyObject implementing MyInterface

public class MyObject : IMyInterface { ...}

public List<MyObject> MyObjectList;

How can I return an IEnumerable<IMyInterface> with the contents of MyObjectList?

I mean, right now I have this:

List<IMyInterface> temp = new List<IMyInterface>();
foreach (MyObject obj in MyObjects) temp.Add(obj);
return (IEnumerable<IMyInterface>)temp;

But is it necessary to create a new list like this?

Thank you.

+5  A: 

If you're using .NET 3.5, the easiest way to do this is:

return MyObjects.Cast<IMyInterface>();

You don't need to create a copy of everything - but until C# 4 comes out with its generic interface variance, you're stuck doing something like this.

If you're still using .NET 2.0, you can easily do something similar:

public static IEnumerable<TResult> SafeCast<TSource, TResult>
    (IEnumerable<TSource> source) where TResult : TSource
{
    foreach (TSource item in source)
    {
        yield return item;
    }
}

(Note that this doesn't check for source being null; to do that properly you'd want two methods due to the deferred execution of iterator blocks.)

Then use:

return SafeCast<MyObject, IMyInterface>(MyObjects);

You could make it more like the LINQ version, like this:

public static IEnumerable<T> SafeCast<T>(IEnumerable source)
{
    foreach (T item in source)
    {
        yield return item;
    }
}

return SafeCast<IMyInterface>(MyObjects);

This has compile-time safety though - it wouldn't stop you from trying to convert a List<string> into an IEnumerable<Guid> for example.

Jon Skeet
Thank you very much Jon, that made concepts more clear for me!
Habitante
A: 

Using the LINQ Cast method works well here, something like MyObjects.Cast()

dsolimano
A: 

If you're using C# 3 and .NET 3.5 (or above), then you can use the LINQ suggestion that Jake presented:

return MyObjectList.Cast<IMyInterface>();

(There's no need for AsEnumerable in this particular circumstance)

However, if you're using a prior version (2.0 of C# and .NET or above), you can still use an iterator block:

foreach(MyObject obj in MyObjectList) yield return (IMyInterface)obj;
Adam Robinson