Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extension Method for a Collection of Derived Types with Base Type in Method Signature

I want to write an extension method for a collection of objects that uses base class as a type requirement. I understand this is not necessarily the best way to do things, but I am curious because I'm interested in learning the nuances of the language. This example explains what I would like to do.

public class Human { public bool IsHappy { get; set; } }
public class Man : Human { public bool IsSurly { get; set; } }
public class Woman : Human { public bool IsAgreeable { get; set; } }

public static class ExtMethods
{
    public static void HappinessStatus(this IEnumerable<Human> items)
    {
        foreach (Human item in items)
        {
            Console.WriteLine(item.IsHappy.ToString());
        }
    }
}

// then in some method, I wish to be able to do the following

List<Woman> females = RetreiveListElements(); // returns a list of Women
females.HappinessStatus(); // prints the happiness bool from each item in a collection

The only way I can get the extension method to expose is to create a collection of Humans. Is it possible to call this type of extension method on derived types as long as I only reference members of the base type?

like image 976
Nate Avatar asked Mar 25 '11 03:03

Nate


1 Answers

Your code will actually compile as is with the C# 4 compiler, as that version supports contravariant type parameters.

To get it working with C# 3, you can create a generic extension method for IEnumerable<T> with a where T : Human constraint that acts on the generic type, instead of specifically only for IEnumerable<Human>:

public static void HappinessStatus<T>(this IEnumerable<T> items) where T : Human
{
    foreach (T item in items)
    {
        Console.WriteLine(item.IsHappy.ToString());
    }
}

Then you can call the extension method on your List<Woman> collection as you describe.

like image 66
BoltClock Avatar answered Oct 03 '22 14:10

BoltClock