为什么不通过ref返回集合元素?

Ban*_*San 21 .net c# c#-7.0

以下通过引用返回的示例来自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");
}
Run Code Online (Sandbox Code Playgroud)

编译没有任何问题(正如你所期望的那样,它是从微软博客中复制的).

我写过这个:

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];
}
Run Code Online (Sandbox Code Playgroud)

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

CS8156表达式不能在此上下文中使用,因为它可能不会通过引用返回

为什么从数组返回工作,但从集合返回不?

Mar*_*ari 17

答案就在您发布的相同链接中:

您只能返回"安全返回"的引用:传递给您的引用,以及指向对象中的字段的引用.

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

  • 还有更多:`Dictionary <,>`的索引属性不是`ref`的有效表达式.你不能提供`ref passwords [searchTerm]`作为ref参数.因此,编译器不会评估ref是否可以安全返回,因为它根本不是有效的ref. (7认同)
  • @acelent是的我同意.这个答案有误导性.它与`password`无关是本地的.这是因为ref表达式正在调用索引器. (2认同)

ace*_*ent 17

在C#中,ref适用于:

  • 变量(本地或参数)
  • 字段
  • 数组位置

ref 不起作用:

  • 属性
  • 活动
  • C#7中的局部变量由ref返回

请注意,对于字段和数组位置,访问阵列的方式无关紧要.也就是说,return ref numbers[i];不坚持numbers,但它指向的数组.完全不同return ref numbers;,只有numbers在一个领域才能发挥作用.

但是,你正在使用ref一个Dictionary<,>索引属性,它不是一个支持的表达式ref开始(即你不能ref passwords[searchTerm]在C#7之前作为参数传递),更不用说返回ref.