views:

85

answers:

3

I have a collection defined as:

public class MyCollection : List<MyItem>
{
    ...
}
public class MyItem
{
    ...
}

Using linq, I can use the Select method to return a IEnumerable, and I can call .ToList on that to get an IList but is there some way of getting back a type of MyCollection? Because I am tring to instantiate a class which has a property of type MyCollection, and I want to use object initialization.

For example:

public class MyClass
{
    MyCollection TestCollection {get;set}
    ...
}

MyClass test = new MyClass()
{
    ...
    TestCollection = SomeObject.Select(item => new MyItem()
    {
        ...
    }).ToList();
}

I get a compile error because ToList returns List and it can't cast to a MyCollection object. Is there a way to do that?

+1  A: 

You could make your own extension method that builds your collection from an IEnumerable, like

public static class Extensions
{
    public static MyCollection ToMyCollection(this IEnumerable<MyItem> items)
    { 
        //build and return your collection
    }
}

or if MyItem is a placeholder for generic types in your context :

public static class Extensions
{
    public static MyCollection ToMyCollection<T>(this IEnumerable<T> items)
    {
        //build and return your collection
    }
}
Dynami Le Savard
+1  A: 

You'll need to construct your MyCollection instance with the IEnumerable<MyItem>. Add a constructor like:

public MyCollection(IEnumerable<MyItem> items) : base(items) {}

Then, when you go to use this, you can do:

TestCollection = new MyCollection(SomeObject.Select(item => new MyItem());
Reed Copsey
A: 

Just mimic ToList:

public static class MyCollectionExtensions {
  public static MyCollection ToMyCollection(this IEnumerable<MyItem> source) {
    if (source == null) throw new NullReferenceException();
    return new MyCollection(source);
  }
}

MyCollection needs a new constructor:

public class MyCollection : List<MyItem> {
  public MyCollection() : base() { }
  public MyCollection(IEnumerable<MyItem> source) : base(source) { }
  ...
} 

Also, it's generally not advisable to expose a setter for a collection. You should encapsulate mutation of the collection inside the class:

public class MyClass {
  public MyCollection TestCollection { get { ... } } // should return a read-only collection
  public void Add(MyItem item) {
    _testCollection.Add(item);
  }
  MyCollection _testCollection = ...;
  ...
} 
Jordão