Почему не возвращается 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 Выражение не может использоваться в этом контексте, потому что оно не может быть возвращено ссылкой
Почему возвращается из массива, но возврат из коллекции не выполняется?
Ответы
Ответ 1
Ответ в той же самой ссылке, которую вы опубликовали:
Вы можете возвращать только те ссылки, которые "безопасны для возврата": переданные вам, и те, которые указывают на поля в объектах.
Ваш пример не удовлетворяет ни тем, ни другим. Вы создаете список внутри функции (поэтому объект выходит из области видимости и его указатель будет недопустим), и он не указывает на поле объекта.
Ответ 2
В С#, ref
работает для:
- Переменные (локальные или параметры)
- Поля
- Расположение массивов
ref
не работает для:
- Свойства
- События
- Локальные переменные в случае возврата С# 7 по ref
Обратите внимание, что для полей и местоположений массивов не имеет значения, как вы обращаетесь к массиву. То есть return ref numbers[i];
не относится к numbers
, а относится к массиву, на который указывает. В отличие от return ref numbers;
, который может работать только в том случае, если numbers
было полем.
Однако вы используете ref
для свойства индекса Dictionary<,>
, это просто не поддерживаемое выражение для ref
для начала (т.е. вы не можете передать ref passwords[searchTerm]
в качестве аргумента еще до С# 7), а тем более возврат по ссылке.