扩展方法的模糊性,其中实现了类型化和非类型化接口

时间:2014-08-26 08:09:22

标签: c# generics ambiguity

考虑以下代码:

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();
    }
}

上面的代码没有问题,IList实现ICollectionIList<T>实现ICollection<T>。如果我们要删除其中一个扩展方法,b()中的一行将无法编译。这就是我宣布两种扩展方法的原因。但是,如果我们调用list.isEmpty()ambiguous call,则会出现问题。但是,因为List<T>实现了 ICollection ICollection<T>。如何环绕这个问题?当然,我可以添加扩展方法isEmpty(this List<T> list),但这自然不会修复任何其他同时实现类型化和非类型化接口的集合(并且适用于任何实现类型化和非类型化的非集合的集合)同一个界面的无类型版本。)

2 个答案:

答案 0 :(得分:1)

您只需添加适用于所有序列的IEnumerable扩展程序。

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

或者

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();
            }
        }
    }
}

答案 1 :(得分:1)

您可以使用反射来确定类型并调用正确的方法,但这可能是一种过度杀伤力。我建议创建一个扩展方法,该方法采用非泛型IEnumerable并像这样实现它:

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

    return true;
}