Mark
Mark

Reputation: 3283

extension method for List<T> is not accepting List<int>

I'm currently experimenting with extension methods. My goal is a extension method for List which finds the first element that fits the given element in a collection, after a specified index.

public static class Extensions
    {
        public static T FindFirstAfterIndex<T>(this List<T> list, int index, T item) where T : class                                                                                    where T : struct
        {
            return list.Skip<T>(index).Where<T>(result => result == item).First<T>();
        }
    }

so this works for class objects as T.

I also tried:

public static T FindFirstAfterIndex<T>(this List<T> list, int index, T item) where T : class          
                                                                             where T : struct
{
    return list.Skip<T>(index).Where<T>(result => result == item).First<T>();
}

I'm very new in the generic stuff an T so how can i define my where clause to accept also List<int> ?

regards Mark

Upvotes: 1

Views: 1962

Answers (4)

Reza ArabQaeni
Reza ArabQaeni

Reputation: 4907

public static class Extensions
{
    public static T FindFirstAfterIndex<T>(this List<T> list, int index, T item)
        where T :IComparable
    {
        return list.Skip<T>(index).Where<T>(result => result.CompareTo(item)==0).First<T>();
    }
}

Upvotes: 1

Mike Christensen
Mike Christensen

Reputation: 91598

int is not a class. int will be boxed into a struct (Int32).

You'd have to remove the clause:

where T : class

Or use Int32? instead.

Update:

Int32? will most likely not work, since technically it will still be a struct:

public struct Nullable<T> where T : struct

Your best bet is to remove the class constraint if you want to use structs here.

Upvotes: 6

Jon Skeet
Jon Skeet

Reputation: 1500245

Your extension method in invalid in terms of its constraints:

   public static T FindFirstAfterIndex<T>(this List<T> list, int index, T item) 
       where T : class  where T : struct

(The where T : struct constraint is scrolled all the way over to the right on your question.)

You can't specify two constraint clauses for the same type parameter like this. You can specify one constraint clause with multiple constraints (e.g. where T : class, IDisposable), but it can't include both the class and struct constraints.

If your extension method really only has one constraint and that constraint is where T : class, then that explains why it's not valid for List<int> - because int doesn't satisfy the reference type constraint.

Frankly your method would be better off written like this:

public static T FindFirstAfterIndex<T>(this IEnumerable<T> list,
                                       int index, T item)
{
    return FindFirstAfterIndex(list, index, item, EqualityComparer<T>.Default);
}

public static T FindFirstAfterIndex<T>(this IEnumerable<T> list,
                                       int index, T item,
                                       IEqualityComparer<T> comparer)
{
    return list.Skip(index)
               .Where(result => comparer.Equals(result, item))
               .First();
}

Now it will work for any list, and will use the default equality semantics of T (which will make it work more conventionally for List<string> for example) and also allow you to supply a custom equality comparer when you want to.

Upvotes: 9

BrokenGlass
BrokenGlass

Reputation: 160862

Just drop the class constraint:

public static T FindFirstAfterIndex<T>(this List<T> list, int index, T item) 
{

}

Upvotes: 6

Related Questions