Подтвердить что ты не робот

Свойство или индексатор не может передаваться как параметр out или ref

Я получаю вышеуказанную ошибку и не могу ее разрешить. Я немного искал Google, но не могу избавиться от него.

Сценарий:

У меня есть класс BudgetAllocate, у которого есть бюджет, который имеет двойной тип.

В моем dataAccessLayer

В одном из моих классов я пытаюсь сделать это:

double.TryParse(objReader[i].ToString(), out bd.Budget);

Что вызывает эту ошибку:

Свойство или индексатор не могут быть переданы в качестве параметра out или ref в время компиляции.

Я даже пробовал это:

double.TryParse(objReader[i].ToString().Equals(DBNull.Value) ? "" : objReader[i].ToString(), out bd.Budget);

Все остальное работает нормально, а ссылки между слоями присутствуют.

4b9b3361

Ответ 1

вы не можете использовать

double.TryParse(objReader[i].ToString(), out bd.Budget); 

замените bd.Budget на некоторую переменную.

double k;
double.TryParse(objReader[i].ToString(), out k); 

Ответ 2

Другие предоставили вам решение, но почему это необходимо: свойство является просто синтаксическим сахаром для метода.

Например, когда вы объявляете свойство под названием Name с помощью геттера и сеттера, под капотом компилятор фактически генерирует методы, называемые get_Name() и set_Name(value). Затем, когда вы читаете и записываете это свойство, компилятор переводит эти операции в вызовы этих сгенерированных методов.

Когда вы это рассматриваете, становится очевидным, почему вы не можете передать свойство в качестве выходного параметра - вы действительно должны передавать ссылку на метод, а не ссылку на объект a переменная, которую ожидает выходной параметр.

Аналогичный случай существует для индексаторов.

Ответ 3

Это случайная абстракция. Свойством на самом деле является метод, get и set accessors для индексатора скомпилированы в методы get_Index() и set_Index. Компилятор делает потрясающую работу, скрывающую этот факт, он автоматически переводит присваивание свойству соответствующему методу set_Xxx(), например.

Но это происходит вверх, когда вы передаете параметр метода по ссылке. Это требует, чтобы компилятор JIT передавал указатель на ячейку памяти переданного аргумента. Проблема в том, что ее нет, присваивание значения свойства требует вызова метода setter. Вызываемый метод не может отличить переданную переменную от переданного свойства и поэтому не может знать, требуется ли вызов метода.

Примечательно, что это действительно работает в 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, выраженного в С#:

int temp = Prop;
Test(ref temp);
Prop = temp;

Какое обходное решение вы можете использовать. Не совсем уверен, почему команда С# не использовала тот же подход. Возможно, потому, что они не хотели скрывать потенциально дорогостоящие вызовы getter и setter. Или полностью недиагностируемое поведение, которое вы получите, когда у сеттера есть побочные эффекты, которые изменяют значение свойства, они исчезнут после назначения. Классическая разница между С# и VB.NET, С# "не сюрпризов", VB.NET "заставляет работать, если вы можете".

Ответ 4

Поместите параметр out в локальную переменную, а затем установите переменную в bd.Budget:

double tempVar = 0.0;

if (double.TryParse(objReader[i].ToString(), out tempVar))
{
    bd.Budget = tempVar;
}

Обновление: прямо из MSDN:

Свойства не являются переменными и поэтому не могут быть переданы как параметры.

Ответ 5

Возможно интересный - вы можете написать свой собственный:

    //double.TryParse(, out bd.Budget);
    bool result = TryParse(s, value => bd.Budget = value);
}

public bool TryParse(string s, Action<double> setValue)
{
    double value;
    var result =  double.TryParse(s, out value);
    if (result) setValue(value);
    return result;
}

Ответ 6

Это очень старый пост, но я исправляю принятый, потому что есть еще более удобный способ сделать это, которого я не знал.

Он вызывал встроенное объявление и, возможно, всегда был доступен (как при использовании операторов), или он мог быть добавлен с С# 6.0 или С# 7.0 для таких случаев, не уверен, но все равно работает как шарм:

Inetad этого

double temp;
double.TryParse(objReader[i].ToString(), out temp);
bd.Budget = temp;

использовать этот:

double.TryParse(objReader[i].ToString(), out double temp);
bd.Budget = temp;

Ответ 7

Итак, бюджет - это свойство, правильно?

Скорее сначала установите его на локальную переменную, а затем установите для него значение свойства.

double t = 0;
double.TryParse(objReader[i].ToString(), out t); 
bd.Budget = t;