Подтвердить что ты не робот

Почему не возвращается ref ref для элементов коллекций?

Следующий пример возврата по ссылке - Что нового в С# 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 Выражение не может использоваться в этом контексте, потому что оно не может быть возвращено ссылкой

Почему возвращается из массива, но возврат из коллекции не выполняется?

4b9b3361

Ответ 1

Ответ в той же самой ссылке, которую вы опубликовали:

Вы можете возвращать только те ссылки, которые "безопасны для возврата": переданные вам, и те, которые указывают на поля в объектах.

Ваш пример не удовлетворяет ни тем, ни другим. Вы создаете список внутри функции (поэтому объект выходит из области видимости и его указатель будет недопустим), и он не указывает на поле объекта.

Ответ 2

В С#, ref работает для:

  • Переменные (локальные или параметры)
  • Поля
  • Расположение массивов

ref не работает для:

  • Свойства
  • События
  • Локальные переменные в случае возврата С# 7 по ref

Обратите внимание, что для полей и местоположений массивов не имеет значения, как вы обращаетесь к массиву. То есть return ref numbers[i]; не относится к numbers, а относится к массиву, на который указывает. В отличие от return ref numbers;, который может работать только в том случае, если numbers было полем.

Однако вы используете ref для свойства индекса Dictionary<,>, это просто не поддерживаемое выражение для ref для начала (т.е. вы не можете передать ref passwords[searchTerm] в качестве аргумента еще до С# 7), а тем более возврат по ссылке.