当序列包含默认值时,使用SingleOrDefault()

本文关键字:使用 SingleOrDefault 包含 默认值 | 更新日期: 2023-09-27 18:19:44

我偶然发现了一个有趣的场景,但我找不到解决方案。假设我必须找到序列中的多数(至少出现n / 2 + 1次的数字,其中n是序列的大小)。这是我的实现:

public static int FindMajorant(IList<int> numbers)
{
    return numbers
        .GroupBy(x => x)
        .Where(g => g.Count() >= numbers.Count / 2 + 1)
        .Select(g => g.Key)
        .SingleOrDefault();
}

我使用的是SingleOrDefault(),如果在序列中找到元素,它会返回元素或类型的默认值:在这种情况下,它将返回0,因为它是int的默认值。例如,我的方法返回以下序列的3

List<int> sampleNumbers = new List<int>() { 2, 2, 3, 3, 2, 3, 4, 3, 3 };

这是预期的行为。

然而,如果序列中的多数为零(0),会发生什么?它会返回0,但那样的话,我怎么能确定它是SingleOrDefault()中的零作为默认值,还是多数?也许,我可以使用Single(),但这会抛出一个非常错误的异常。我也可能遇到这种例外,但这对我来说似乎是一种糟糕的做法。所以我的问题是,处理这种情况的首选方法是什么?

当序列包含默认值时,使用SingleOrDefault()

null表示不存在多数的情况下使用可为null的值,而不是使用"0"表示。非常方便的是,int?的默认值是null,因此代码所需的唯一更改就是在调用SingleOrDefault之前获得一系列可为null的int。

public static int? FindMajorant(IList<int> numbers)
{
    return numbers
        .GroupBy(x => x)
        .Where(g => g.Count() >= numbers.Count / 2 + 1)
        .Select(g => (int?)g.Key)
        .SingleOrDefault();
}

您可以将结果投影到一个类型化的对象中,比如MajorantResult,然后返回null:

    public static MajorantResult FindMajorant(IList<int> numbers)
    {
        return numbers
            .GroupBy(x => x)
            .Where(g => g.Count() >= numbers.Count/2 + 1)
            .Select(g => new MajorantResult(g.Key))
            .SingleOrDefault();
    }
    public class MajorantResult
    {
        public int Key { get; }
        public MajorantResult(int key)
        {
            this.Key = key;
        }
    }