1

This is an issue I have seen in two different jobs that use a 3-tier structure and haven't found a clean way around it. This also applies to using LINQ statements I believe.

I have 2 classes, one is an object and the other is a defined collection of those objects that might have some additional functionality in it:

    public class TestObject
    {
       public Int32 id     {get; set;}
       public string value {get; set;}
    }

    public class TestObjectCollection: List<TestObject>
    {
       public TestObject Get(Int32 id)
       {
          return this.FirstOrDefault(item => item.id==id);
       }
    }

Say I use a lambda expression like:

    List<TestObject> result = data.Where(item => item.id > 0).ToList();

Is there an easy way to convert that list of objects to my defined collection without doing something like this:

    TestObjectCollection resultAsCollection = new TestObjectCollection()
    resultAsCollection.AddRange(result);

It seems like there should be a way to cast my GenericList returned by the Lambda expression to my TestObjectCollection without the added step looping through my returned results.

3
  • I can't see the problem with using a List<T>, or EnhancedList<T>, or AddRange(IEnumerable<T>). AddRange typically accepts an IEnumerable<T> , which means you can pass the LINQ query directly. The problem is more likely in the implementation of TestObjectCollection Commented Aug 7, 2015 at 14:34
  • You want to replace the .ToList() call with a different extension method that creates your desired list type. Commented Aug 7, 2015 at 14:36
  • Maybe you should write an extension method to DBSet or List. Commented Aug 7, 2015 at 14:38

2 Answers 2

6

No, there isn't. ToList creates a List<T> - and there's no way of casting a plain List<T> to a TestObjectCollection without creating a new TestObjectCollection.

Personally I'd avoid creating a collection deriving from List<T> at all (I'd almost always use composition instead) but if you really want to have that collection, the simplest approach is to create your own extension method:

public static class TestEnumerable
{
     public static TestObjectCollection ToTestObjectCollection(this IEnumerable<TestObject> source)
     {
         return new TestObjectCollection(source);
     }
}

... and implement the appropriate constructor, of course, which can probably just chain to the List(IEnumerable<T>) constructor. Then you can write:

var resultAsCollection = data.Where(item => item.id > 0).ToTestObjectCollection();
Sign up to request clarification or add additional context in comments.

Comments

0

It seems like there should be a way to cast my GenericList returned by the Lamda expression to my TestObjectCollection without the added step looping through my returned results

There isn't because with generic collections you can use covariance and not contravariance.

Other than Jon's solution (which is good) you can create constructor overload:

  public class TestObjectCollection: List<TestObject>
  {
     public TestObjectCollection(IEnumerable<TestObject> list) { AddRange(list);}
     ...
  }

Usage:

var resultAsCollection = new TestObjectCollection(data.Where(item => item.id > 0));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.