为什么按 ref 返回对集合元素不起作用?

Why doesn't returning by ref work for elements of collections?

下面引用返回的例子来自What’s New in C# 7.0:

public ref int Find(int number, int[] numbers)
{
    for (int i = 0; i < numbers.Length; i++)
    {
        if (numbers[i] == number)
        {
            return ref numbers[i]; // return the storage location, not the value
        }
    }
    throw new IndexOutOfRangeException($"{nameof(number)} not found");
}

编译没有任何问题(如您所料,因为它是从 Microsoft 博客复制的)。

我写过这个:

private static ref int GetReference(string searchTerm)
{
    var passwords = new Dictionary<string, int>
    {
        {"password", 1},
        {"123456", 2},
        {"12345678", 3},
        {"1234", 4},
        {"qwerty", 5},
        {"12345", 6},
        {"dragon", 7}
    };

    return ref passwords[searchTerm];
}

虽然这个不能编译;它给出以下错误:

CS8156 An expression cannot be used in this context because it may not be returned by reference

为什么从数组返回有效,但从集合返回无效?

答案与您发布的 link 相同:

You can only return refs that are “safe to return”: Ones that were passed to you, and ones that point into fields in objects.

你的例子都不满足。您正在函数内部创建列表(因此对象将超出范围并且其指针将无效),并且它不指向对象的字段。

在 C# 中,ref 适用于:

  • 变量(局部或参数)
  • 字段
  • 数组位置

ref 不适用于:

  • 属性
  • 活动
  • C# 7 中的局部变量 return by ref

请注意,对于字段和数组位置,访问数组的方式并不重要。也就是说,return ref numbers[i]; 不保留 numbers,而是保留它指向的数组。与 return ref numbers; 完全不同,后者只有在 numbers 是一个字段时才有效。

但是,您在 Dictionary<,> 的索引 属性 上使用 ref,它根本不是 ref 开头的受支持表达式(即您即使在 C# 7 之前也不能将 ref passwords[searchTerm] 作为参数传递,更不用说通过 ref.

传递给 return