2

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.

Habitante
  • 233
  • 3
  • 8
  • Why not create the original list as: public List MyObjectList; Then you can populate it with any object that implements that interface. For me, that would be the normal approach and why I'd define an interface in this manner. What's the objective of your code, that may help and might even reveal that an interface isn't the answer you are looking for. – Lazarus Jan 12 '10 at 16:30
  • 1
    FYI, this conversion will be legal in C# 4. See my archive of notes on the design of this C# 4 feature if this topic interests you: http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx – Eric Lippert Jan 12 '10 at 16:35
  • If I create a List there's some binding properties that won't be picked up by XAML when ItemsSource to the list – Habitante Jan 12 '10 at 16:35
  • Perhaps you could clarify, I don't understand "picked up by XAML", do you mean "picked up by WPF"? – Lazarus Jan 12 '10 at 16:40
  • Yes, I meant WPF, but I might be wrong, I think I just found another reason why it wasn't picking up the binding ... So I think you might be right, declaring a List might solve all issues. Thank you. – Habitante Jan 12 '10 at 16:44

3 Answers3

6

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
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

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

dsolimano
  • 8,870
  • 3
  • 48
  • 63
0

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
  • 182,639
  • 35
  • 285
  • 343