stealthjong
stealthjong

Reputation: 11093

Ambiguity with extension methods where both typed and untyped interface are implemented

Consider this code:

public static class Extensions {
    public static bool isEmpty<T>(this ICollection<T> collection) {
        return collection.Count == 0;
    }

    public static bool isEmpty(this ICollection collection) {
        return collection.Count == 0;
    }
}

public class A {
    IList<string> typedList;
    IList rawList;
    List<string> list;

    public void b() {
        bool d = typedList.isEmpty();
        bool e = rawList.isEmpty();
    }
}

Above code is no problem, for IList implements ICollection, and IList<T> implements ICollection<T>. Were we to remove one of the extension methods, one of the lines in b() wouldn't compile. That's why I declared both extension methods. However, a problem surfaces if we call list.isEmpty(): ambiguous call. That is, however, because List<T> implements both ICollection and ICollection<T>. How to circumnavigate this problem? Of course, I can add the extension method isEmpty(this List<T> list), but that, naturally, doesn't fix any other collections which implement both a typed and an untyped interface (and that goes for any non-collections which implement a typed and an untyped version of the same interface as well).

Upvotes: 2

Views: 205

Answers (2)

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101681

You can use reflection to determine the type and call the proper method but that would be an overkill. I would suggest creating an extension method that takes non-generic IEnumerable and implement it like this:

public static bool isEmpty(this IEnumerable collection) 
{
    var enumerator = collection.GetEnumerator();
    if(enumerator.MoveNext()) return false;

    return true;
}

Upvotes: 1

Sriram Sakthivel
Sriram Sakthivel

Reputation: 73442

You can simply add Extension for IEnumerable which will work for all sequences.

public static class Extensions
{
    public static bool IsEmpty(this IEnumerable collection)
    {
        return !collection.Cast<object>().Any();
    }
}

Or

public static class Extensions
{
    public static bool IsEmpty(this IEnumerable collection)
    {
        IEnumerator enumerator = null;
        try
        {
            enumerator = collection.GetEnumerator();
            return !enumerator.MoveNext();
        }
        finally
        {
            IDisposable disposable = enumerator as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
        }
    }
}

Upvotes: 1

Related Questions