0

啊!好吧,我将把它作为一个问题发布,因为我不知道为什么我会看到这个错误......但当然,当我看到它时,它现在是如此明显。现在拍自己的头。不过,我会把它留在这里取乐。看看你能不能抓住它。

今晚在为 WeakDictionary 类实现 TryGetValue 时,我遇到了一些奇怪的事情。我收到一个错误,我不知道为什么。

这是代码:

public bool TryGetValue(TKey key, out TItem value)
{
    WeakReference<TItem> weakReference;

    if(_itemStorage.TryGetValue(key, out weakReference))
        if(weakReference.TryGetTarget(out value))
            return true;
    else
        value = default(TItem);

    return false;
}

这是我得到的错误:

在控制离开当前方法之前,必须分配 out 参数“值”。

在我看来,所有代码路径在返回之前都设置了“值”。

如果第一个“if”失败,则“else”子句设置“value”。

但是,如果第一个“if”通过,则下一行“weakReference.TryGetTarget”是否设置了“值”,原因与我被警告的完全相同(即“TryGetTarget”本身有一个“out”参数,因此它也必须在返回之前在内部设置其 out 参数)?

就像我说的,我遗漏了一些明显的东西。(我需要睡觉!)

4

3 回答 3

7

问题在于,如果您的第一个 if 语句失败,您将留下未初始化的值。

基本上,您的if语句中缺少花括号,这将使else语句正确附加到正确的if

if (_itemStorage.TryGetValue(key, out weakReference))
{
    if (weakReference.TryGetTarget(out value))
        return true;
}

文档清除了这一点:

then 语句和 else 语句中的一个或多个语句可以是任何类型的,包括嵌套在原始 if 语句中的另一个 if 语句。在嵌套的 if 语句中,每个 else 子句都属于最后一个没有相应 else 的 if。

这意味着,您的else子句被附加到内部if语句,而不是外部语句。

您也可以将其重写为:

public bool TryGetValue(TKey key, out TItem value)
{
    WeakReference<TItem> weakReference;

    if (_itemStorage.TryGetValue(key, out weakReference))
        return weakReference.TryGetTarget(out value);

    value = default(TItem);
    return false;
}
于 2015-09-20T06:08:31.813 回答
4

删除else声明。

实际上与@Yuval 的答案相同,但我喜欢删除代码。

public bool TryGetValue(TKey key, out TItem value)
{
  WeakReference<TItem> weakReference;

  if(_itemStorage.TryGetValue(key, out weakReference))
    if(weakReference.TryGetTarget(out value))
        return true;

  value = default(TItem);

  return false;
}

另请注意,这if(c1) if(c2)相当于if (c1 && c2); 哪个读起来更好,不会有你的问题。

于 2015-09-20T06:11:46.067 回答
2

您的代码正在编译为:

public bool TryGetValue(TKey key, out TItem value)
{
    WeakReference<TItem> weakReference;

    if (_itemStorage.TryGetValue(key, out weakReference))
    {
        if (weakReference.TryGetTarget(out value))
        {
            return true;
        }
        else
        {
            value = default(TItem);
        }
    }

    return false;
}

在此代码中,如果第一个为 false value,则不会设置变量。if

你真正想要的——并且认为你得到了——是这样的:

public bool TryGetValue(TKey key, out TItem value)
{
    WeakReference<TItem> weakReference;

    if (_itemStorage.TryGetValue(key, out weakReference))
    {
        if (weakReference.TryGetTarget(out value))
        {
            return true;
        }
    }
    else
    {
        value = default(TItem);
    }

    return false;
}

这是不指定大括号并假设列位置else正确的危险。

于 2015-09-20T06:33:03.203 回答