Здесь приведен пример метода экземпляра struct, пытающегося вернуть refonly ref в поле экземпляра структуры:
struct Foo
{
internal int _x;
public ref readonly int MemberGetX() => ref _x;
// ^^^
// Error CS8170: Struct members cannot return 'this' or other instance members by reference
}
Это приводит к ошибке. Члены CS8170 Struct не могут возвращать "этот" или другие члены экземпляра по ссылке. Тем не менее, выполнение одной и той же функции с использованием метода расширения не вызывает ошибки:
static class FooExtensions
{
public static ref readonly int ExtensionGetX( this in Foo foo )
{
return ref foo._x;
}
}
Ответы на связанный вопрос Почему структура С# не может ссылаться на поле своего члена? обсудите причины, по которым язык не разрешает первый сценарий, но с учетом этих причин мне непонятно, почему разрешен второй сценарий.
Обновить:
Здесь приведен полный пример, который не использует readonly
, а также показывает метод без расширения и демонстрирует использование:
struct Foo
{
internal int _x;
// Can't compile, error CS8170
// public ref int GetXRefMember() => ref _x;
public int X => _x;
}
static class FooExtensions
{
public static ref int GetXRefExtension( this ref Foo foo )
{
return ref foo._x;
}
public static ref int GetXRef( ref Foo foo )
{
return ref foo._x;
}
}
class Program
{
static void Main( string[] args )
{
var f = new Foo();
Console.WriteLine( f.X );
f.GetXRefExtension() = 123;
Console.WriteLine( f.X );
// You can also do it without using an extension method, but the caller is required to specify ref:
FooExtensions.GetXRef( ref f ) = 999;
Console.WriteLine( f.X );
/* Output:
* 0
* 123
* 999
*/
}
}
Интересно, что методы расширения молча добавляют "add" ref
, когда нормальные вызовы требуют, чтобы вызывающий ящик явно добавлял ref
в аргумент, я предполагаю, что он станет ясным и предотвратит ошибки.