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