LINQBridge IComparer例外

时间:2011-12-01 23:07:25

标签: c# linq linqbridge

我正在使用针对.NET 2.0 Framework的LINQ Bridge,我收到以下错误。只想要随机选择的集合中的第一个元素。不关心这种特殊情况下的表现。

var result = someCollection.OrderBy(g => Guid.NewGuid()).Take(1).FirstOrDefault();

someCollection是List<string>。集合中的值是唯一的。

  

无法排序,因为IComparer.Compare()方法返回   结果不一致。要么值不等于自身,   或者与另一个值重复比较的一个值产生不同   结果。 x:'',x的类型:'元组2', IComparer: 'System.Array+FunctorComparer 1 [LinqBridge.Tuple`2 [System.String,System.Int32]]'。

但它似乎在.NET 4.0中运行得很好。这有解决方法吗?不幸的是,我坚持使用.NET 2.0来实现这种情况。

编辑使用最新版本的LINQ Bridge(1.2)

1 个答案:

答案 0 :(得分:2)

又一次更新

我发现这个问题与您有同样的问题: Why does using Random in Sort causing [Unable to sort IComparer.Compare error]
问题是LINQBridge在内部使用List<>.Sort,当使用“不稳定”比较算法时会抱怨,所以遗憾的是你无法以这种方式随机化。

作为替代方案,这里有一些很棒的代码可以随机化或选择一个随机项目:

    private static Random rnd = new Random();
    /// <summary>
    /// Chooses one of the items at random.
    /// 
    /// Returns default if there are no items.
    /// </summary>
    public static T RandomOrDefault<T>(this IEnumerable<T> source)
    {
        // We need the count:
        var buffer = source as ICollection<T> ?? source.ToList(); // (iterate only once)
        var itemCount = buffer.Count;
        if (itemCount == 0)
        {
            return default(T);
        }

        var index = rnd.Next(itemCount);
        return buffer.ElementAt(index);
    }

    /// <summary>
    /// Randomizes the order of the elements of a sequence. 
    /// </summary>
    public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
    {
        // This code is an implementation of the Fisher–Yates shuffle.
        // The code was obtained from:
        // https://stackoverflow.com/questions/1287567/c-is-using-random-and-orderby-a-good-shuffle-algorithm/1665080#1665080
        T[] elements = source.ToArray();
        // Note i > 0 to avoid final pointless iteration
        for (int i = elements.Length - 1; i > 0; i--)
        {
            // Swap element "i" with a random earlier element it (or itself)
            int swapIndex = rnd.Next(i + 1);
            yield return elements[swapIndex];
            elements[swapIndex] = elements[i];
            // we don't actually perform the swap; we can forget about the
            // swapped element because we already returned it.
        }

        // there is one item remaining that was not returned - we return it now
        yield return elements[0];
    }

更新

此异常看起来像LINQBridge错误。 我建议更新到最新版本。没有其他明显的理由让你看到这个问题。

其他信息

您可以使用Random代替Guid,如下所示:

var rnd = new Random();
var result = someCollection.OrderBy(g => rnd.Next()).Take(1).FirstOrDefault();

此外,.Take(1)

后跟.FirstOrDefault()完全没必要