Это случай дырявой абстракции. Свойство на самом деле является методом, методы доступа get и set для индексатора компилируются в методы get_Index () и set_Index. Компилятор делает потрясающую работу, скрывая этот факт, например, он автоматически переводит присвоение свойству соответствующего метода set_Xxx ().
Но это идет вверх, когда вы передаете параметр метода по ссылке. Это требует, чтобы JIT-компилятор передавал указатель на ячейку памяти переданного аргумента. Проблема в том, что его нет, присвоение значения свойства требует вызова метода установки. Вызываемый метод не может отличить переданную переменную от переданного свойства и, следовательно, не может знать, требуется ли вызов метода.
Примечательно то, что это действительно работает в VB.NET. Например:
Class Example
Public Property Prop As Integer
Public Sub Test(ByRef arg As Integer)
arg = 42
End Sub
Public Sub Run()
Test(Prop) '' No problem
End Sub
End Class
Компилятор VB.NET решает эту проблему, автоматически генерируя этот код для метода Run, выраженный на C #:
int temp = Prop;
Test(ref temp);
Prop = temp;
Это обходной путь, который вы также можете использовать. Не совсем понимаю, почему команда C # не использовала тот же подход. Возможно, потому что они не хотели скрывать потенциально дорогие вызовы геттеров и сеттеров. Или совершенно недиагностируемое поведение, которое вы получите, когда у установщика есть побочные эффекты, которые изменяют значение свойства, они исчезнут после назначения. Классическая разница между C # и VB.NET, C # - «без сюрпризов», VB.NET - «заставить работать, если можно».