Samantha Branham
Samantha Branham

Reputation: 7441

How can I work around C#'s limitation on calling static functions on a Generic type

I have the following extension method, and would like to make it more generic so I don't have to implement it for every class in our domain.

public static IList<User> ToList(this DataTable table)
{
    IList<User> users = new List<User>();

    foreach (DataRow row in table.Rows)
        users.Add(User.FromDataRow(row));

    return users;
}

Is there any way to work around this frustrating limitation?

edit: the below paragraph is bollocks, but I'm keeping it so one of the answers makes sense to future readers:

User, as well as my other classes, implements IDataModel. IDataModel only requires 1 method, FromDataRow(DataRow row). Putting a where into the function prototype obviously doesn't help.

Upvotes: 1

Views: 693

Answers (2)

Bevan
Bevan

Reputation: 44307

In your example code, you're using a static method to create the user from the DataRow:

foreach (DataRow row in table.Rows)
    users.Add(User.FromDataRow(row));

But, you can't use static methods to implement an interface.

Assuming that your interface looks like this:

public interface IDataModel {
    void FromDataRow(DataRow row);
}

then your User class will have an instance method FromDataRow(), not a static one.

If your classes have parameterless constructors, then you could write this:

public static IList<T> ToList<T>(this DataTable table)
    where T : IDataModel, new()
{
    IList<T> results = new List<T>();

    foreach (DataRow row in table.Rows)
    {
        T item = new T();
        item.FromDataRow(row);
        results.Add(item);
    }

    return users;
}

The IDataModel constraint on <T> requires the type to implement IDataModel.
The new() constraint on <T> requires the type to have a parameterless constructor.

Upvotes: 3

Marc Gravell
Marc Gravell

Reputation: 1062725

When you only need one method, think Func... perhaps a Func<DataRow, T>

public static IList<T> ToList<T>(this DataTable table,
      Func<DataRow,T> converter)
{
    IList<T> list = new List<T>();

    foreach (DataRow row in table.Rows)
        list.Add(converter(row));

    return list;
}

Then call table.ToList<User>(User.FromDataRow)

Upvotes: 9

Related Questions