14

我正在尝试编写 Linq MinBy 扩展方法

public static class Extensions
{
    public static T MinBy<T>(this IEnumerable<T> source, Func<T,int> selector)
    {
        T min;
        int? minKey = null;
        foreach (var x in source)
        {
            var key = selector(x);
            if (minKey == null || key < minKey)
            {
                minKey = key;
                min = x;
            }
        }
        if (minKey == null)
        {
            throw new ArgumentException("source should not be empty");
        }
        return min;
    }
}

我认为我的逻辑是正确且可读的。但我得到一个构建错误

使用未分配的局部变量“min”

我能做些什么呢?我可以测试变量是否已分配?


澄清: MinBy 函数可以回答以下问题。哪个数字 [-5, -2, 3] 的正方形最小?

> new List<int>{-5,-2,3}.MinBy(x => x*x)
-2

.NET 的 Min 函数回答了一个不同的问题(这是最小的正方形)

> new List<int>{-5,-2,3}.Min(x => x*x)
4
4

5 回答 5

26

您需要这样的默认值min

T min = default(T);

default()您可以在 MSDN 上阅读更多信息:

给定参数化类型 T 的变量 t,语句 t = null 仅在 T 是引用类型且 t = 0 仅适用于数值类型而不适用于结构时才有效。解决方案是使用 default 关键字,它将为引用类型返回 null,而为数值类型返回零。对于结构,它将返回结构的每个成员,根据它们是值类型还是引用类型,初始化为零或空。对于可为空的值类型,默认返回一个 System.Nullable,它像任何结构一样被初始化。

于 2012-07-04T09:32:24.450 回答
4

添加一个默认值min

T min = default(T);

它抱怨的原因是编译器无法验证在行min中使用它之前是否已经分配了一个值return min;。无法引用未分配的局部变量,因此编译器会产生错误。

于 2012-07-04T09:33:31.033 回答
1

那是因为 min 是在条件内部分配的。编译器无法确定它是否会得到一个值,你应该用默认值初始化 min。

于 2012-07-04T09:32:34.817 回答
0

,你不能测试一个变量是否被赋值,你总是会得到一个编译错误。

于 2012-07-04T10:57:26.527 回答
-1

仅供参考,这就是我最终得到的

    public static T MinBy<T>(this IEnumerable<T> source, Func<T,int> selector)
    {
        T min = default(T);
        bool started = false;
        int minKey = default(int);
        foreach (var x in source)
        {
            var key = selector(x);
            if (!started || key < minKey)
            {
                minKey = key;
                min = x;
                started = true;
            }
        }
        if (!started)
        {
            throw new ArgumentException("source should not be empty","source");
        }
        return min;
    }
于 2012-07-04T09:57:24.660 回答