检查任意枚举是否有没有泛型的任何项目

时间:2013-08-03 23:39:16

标签: c# wpf windows-runtime ivalueconverter

通常情况下,如果您只想检查IEnumerable<T>中是否有任何项目,请使用.Any()而不是.count > 0 - 尤其是当你遇到像LINQ-To这样的内容时-Entities和.count可能会有严重的性能损失。

我遇到的问题是我正在编写IValueConverter来更改对象的可见性,具体取决于枚举是否包含项目:

public class CollectionEmptyVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var col = value as ICollection;

        if (col == null) { return Visibility.Collapsed.ToString(); }

        return (col.Count > 0) ? Visibility.Visible.ToString() : Visibility.Collapsed.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

因此,在这种情况下,我无法在IEnumerable<T>上使用常规扩展方法,因为此时我无法使用<T>。我当前的实现限制了我实现ICollection的事情,这可能并不总是可取的。

我怎样才能以更有效的方式做到这一点?裸露的IEnumerable(无<T>)没有.Any()

2 个答案:

答案 0 :(得分:3)

这样可以正常工作:

public static class ExtensionMethods
{
    public static bool Any(this IEnumerable t) {
        foreach (var o in t)
            return true;
        return false;
    }
}

基准:

public static class ExtensionMethods
{
    public static bool AnyJR(this IEnumerable t)
    {
        foreach (var o in t)
            return true;
        return false;
    }

    public static bool AnyPhonicUK(this IEnumerable t)
    {
        var e = t.GetEnumerator();
        try {
            return e.MoveNext();
        }
        finally {
            var edisp = e as IDisposable;
            if (edisp != null)
                edisp.Dispose();
        }
    }
}

class Program
{
    static long Test_AnyJR(List<int> l, int n)
    {
        var sw = Stopwatch.StartNew();

        for (int i = 0; i < n; i++) {
            bool any = l.AnyJR();
        }

        sw.Stop();
        return sw.ElapsedMilliseconds;
    }

    static long Test_AnyPhonicUK(List<int> l, int n)
    {
        var sw = Stopwatch.StartNew();

        for (int i = 0; i < n; i++) {
            bool any = l.AnyPhonicUK();
        }

        sw.Stop();
        return sw.ElapsedMilliseconds;
    }

    static void Main(string[] args)
    {
        var list = new List<int> { 1, 2, 3, 4 };

        int N = 10000000;
        Console.WriteLine("{0} iterations using AnyJR took {1} ms.", N, Test_AnyJR(list, N));
        Console.WriteLine("{0} iterations using AnyPhonicUK took {1} ms.", N, Test_AnyPhonicUK(list, N));

        Console.ReadLine();
    }
}

结果:

10000000 iterations using AnyJR took 484 ms.
10000000 iterations using AnyPhonicUK took 393 ms.

答案 1 :(得分:0)

public object Convert(object value, Type targetType, object parameter, string language)
{
    var col = value as ICollection;
    if (col != null)
        return col.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
    var enu = (IEnumerable)value;
    foreach (var obj in enu)
        return true;
    return false;
}

或者(更简洁,但可能是头发更慢):

public object Convert(object value, Type targetType, object parameter, string language)
{
    var enu = (IEnumerable)value;
    return enu.Cast<object>().Any() ? Visibility.Visible : Visibility.Collapsed;
}