Mark
Mark

Reputation: 3283

Extension Method for List<InterfaceType> is not recognized

I'm writing a couple of extension methods for some of our BusinessObjects

for example:

public static IBusinessObject GetBusinessObjectById<T>(this IBusinessObject businessObject, int id)

Now if i create a class:

public class Topic : IBusinessObject

I can then call my extension:

topic.GetBusinessObjectById<Topic>(id);

However that was the working stuff, now i tried to write a extension which focus on List<IBusinessObject>:

public static List<T> GetItems<T>(this List<IBusinessObject> list)

then creating a new List:

List<Topic> topics = new List<Topic>();

topics.GetItems<Topic>(); gives the error

List<Topic> does not contain a definition for GetItems

How can i write an extension method which focuses on a List instance of classes which have implemented my Interface?

Upvotes: 3

Views: 182

Answers (2)

Thomas Levesque
Thomas Levesque

Reputation: 292405

A List<Topic> is not a List<IBusinessObject>, even though Topic implements IBusinessObject; that's because List<T> is not covariant (and anyway, only interfaces and delegates can be covariant, not classes).

If it was, it could cause all sorts of problems; for instance, consider this (hypothetical) extension method:

public static void Foo(this List<IBusinessObject> list)
{
    list.Add(new FooBusinessObject());
}

If you could call this method on a List<BarBusinessObject>, it would add an object of the wrong type, which would cause an exception at runtime.

If your GetItems method isn't going to modify the list, it should accept one of these interfaces instead of List<IBusinessObject>:

  • IEnumerable<IBusinessObject>
  • IReadOnlyCollection<IBusinessObject>
  • IReadOnlyList<IBusinessObject>

All these interfaces are covariant.

Upvotes: 5

Rob Lyndon
Rob Lyndon

Reputation: 12661

An instance of a List<Topic> is not an instance of a List<IBusinessObject>. While IEnumerable<T> is covariant, List<T> is not.

On the other hand, a List<Topic> is also an IEnumerable<Topic>, which is itself an IEnumerable<IBusinessObject>. Therefore if you redefine your extension method as

public static List<T> GetItems<T>(this IEnumerable<IBusinessObject> collection)

then you should have the function you're looking for.

Upvotes: 1

Related Questions