为什么这个方法有一个 'out' 参数说它没有设置?

Why is this this method with an 'out' parameter saying it isn't set?

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

今晚在为我们的 WeakDictionary class 实现 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;
}

这是我遇到的错误:

The out parameter 'value' must be assigned to before control leaves the current method.

在我看来,所有代码路径 do 都在 returns.

之前设置了 'value'

如果第一个 'if' 失败,'else' 子句设置 'value'.

如果第一个 'if' 通过,下一行 'weakReference.TryGetTarget' 是否设置 'value' 与我被警告的原因完全相同(即 'TryGetTarget' 本身有一个 'out' 参数,因此它也必须在内部设置它的 out 参数 returns)?

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

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

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

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

The docs 清除这个:

The statement or statements in the then-statement and the else-statement can be of any kind, including another if statement nested inside the original if statement. In nested if statements, each else clause belongs to the last if that doesn’t have a corresponding else.

这意味着,您的 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;
}

删除 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);哪个读起来更好,不会有你的问题。

您的代码编译如下:

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;
}

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

您真正想要的 - 并认为您得到的 - 是:

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 的列位置正确的危险。