Свойства - это [пара методов получения и установки] с симпатичным синтаксисом для их вызова, который делает их похожими на поля.
Выходные параметры могут быть ссылками на поля или «полями» на основе стека (т. Е. Локальными).
Заполнение этого пробела обычно не решается языками (и определенно не напрямую с помощью моделей CLR и IL). (+1 на @Heinzi за ссылки на обман VB)
Нет, вы не можете использовать свойство в качестве параметра ref
или out
в C #, поскольку среда CLR не поддерживает это. Передача переменной экземпляра должна работать нормально.
В качестве примечания: VB.NET позволяет передавать свойств и использует метод, называемый «копирование по ссылке назад», как объясняется в этой записи блога MSDN .
Вы не можете сделать это с помощью C #.
Вы можете использовать VB.Net, но я считаю это плохой идеей. Следующий код и выходные данные показывают, как он это делает, и показывают, почему я считаю это плохой идеей, вплоть до того, что мне хотелось бы использовать VB.net также не допускал этого
Public Class MySimpleClass
Private _privateInt As Integer
Public PublicInt As Integer
Public Property PrivateInt() As Integer
Get
Return _privateInt
End Get
Set(ByVal value As Integer)
_privateInt = value
End Set
End Property
Public Sub MyNotifier()
Console.WriteLine("PublicInt {0} : PrivateInt {1} : Values are not the same", PublicInt, PrivateInt)
End Sub
End Class
Теперь вызовите это из вспомогательной сети, например
Sub Main()
Dim sampleClass As New MySimpleClass
IterateAndUpdate(sampleClass.PrivateInt, sampleClass.PublicInt, AddressOf sampleClass.MyNotifier)
Console.WriteLine("Private {0} : Public {0} : values are the same ", sampleClass.PrivateInt, sampleClass.PublicInt)
Console.ReadKey()
End Sub
Sub IterateAndUpdate(ByRef anInt As Integer, ByRef anOtherInt As Integer, ByVal notifier As Action)
For i As Integer = 1 To 9
anInt = i
anOtherInt = i
notifier()
Next
End Sub
Это выводит
PublicInt 1: PrivateInt 0: значения не совпадают
PublicInt 2: PrivateInt 0: значения не совпадают
PublicInt 3: PrivateInt 0: значения не совпадают
PublicInt 4: PrivateInt 0: значения не совпадают
PublicInt 5: PrivateInt 0: значения не совпадают
PublicInt 6: PrivateInt 0: значения не совпадают
PublicInt 7: PrivateInt 0: значения не совпадают
PublicInt 8: PrivateInt 0: значения не совпадают
PublicInt 9: PrivateInt 0: значения не совпадают
Private 9: Public 9: значения совпадают
Вы можете видеть, что член PublicInt
при передаче ByRef
немедленно обновляется в sampleClass, поместите PrivateInt
отображается как свойство, обновляется только после завершения метода IterateAndUpdate
.
Следовательно, вы получаете заметно различающееся поведение от одного и того же соглашения о вызовах, и это зависит от того, как вы реализовали переданный элемент (что совсем не очевидно, если посмотреть на вызов IterateAndUpdate
.
Возможность скрыть ошибки или внести небольшие изменения в ожидаемое поведение достаточно для меня, чтобы пожелать, чтобы этой «функции» не существовало.
На мой взгляд, это работает некорректно, поэтому должно быть либо
a) Исправлено, что потребовало бы значительных усилий для команды компилятора и, возможно, внесло бы критические изменения
или
б) Совсем не работает
Вы можете использовать параметр out
с полями (или локальными, как уже было сказано).
Аргумент, переданный параметру out, не может быть свойством. Если вы попытаетесь скомпилировать свой код, вы получите ошибку компиляции.
Доступ к свойству, индексатору или динамическому члену не может быть передан как параметр out или ref
Причина в том, что свойство на самом деле не является полем (у него может быть резервное поле, но может и не быть). Это два метода, которые называются get_Foo
и set_Foo
. См. Свойство C # и параметр ref, почему без сахара? для получения дополнительных объяснений, почему это не работает.
Пример кода, который выдает ошибку компиляции:
class Program
{
public int Foo { get; set; }
public void Bar(out int x)
{
x = 5;
}
void Run()
{
Bar(out Foo); // compile error
}
static void Main()
{
new Program().Run();
}
}