C#: может параметры в функциях быть объектными свойствами/переменными? [дубликат]

9
задан CJ7 6 August 2010 в 08:23
поделиться

5 ответов

Свойства - это [пара методов получения и установки] с симпатичным синтаксисом для их вызова, который делает их похожими на поля.

Выходные параметры могут быть ссылками на поля или «полями» на основе стека (т. Е. Локальными).

Заполнение этого пробела обычно не решается языками (и определенно не напрямую с помощью моделей CLR и IL). (+1 на @Heinzi за ссылки на обман VB)

6
ответ дан 4 December 2019 в 12:16
поделиться

Нет, вы не можете использовать свойство в качестве параметра ref или out в C #, поскольку среда CLR не поддерживает это. Передача переменной экземпляра должна работать нормально.

В качестве примечания: VB.NET позволяет передавать свойств и использует метод, называемый «копирование по ссылке назад», как объясняется в этой записи блога MSDN .

4
ответ дан 4 December 2019 в 12:16
поделиться

Вы не можете сделать это с помощью 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) Исправлено, что потребовало бы значительных усилий для команды компилятора и, возможно, внесло бы критические изменения
или
б) Совсем не работает

4
ответ дан 4 December 2019 в 12:16
поделиться

Вы можете использовать параметр out с полями (или локальными, как уже было сказано).

0
ответ дан 4 December 2019 в 12:16
поделиться

Аргумент, переданный параметру 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();
    }
}
3
ответ дан 4 December 2019 в 12:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: