Ответ 1
вы не можете использовать
double.TryParse(objReader[i].ToString(), out bd.Budget);
замените bd.Budget на некоторую переменную.
double k;
double.TryParse(objReader[i].ToString(), out k);
Я получаю вышеуказанную ошибку и не могу ее разрешить. Я немного искал 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);
Все остальное работает нормально, а ссылки между слоями присутствуют.
вы не можете использовать
double.TryParse(objReader[i].ToString(), out bd.Budget);
замените bd.Budget на некоторую переменную.
double k;
double.TryParse(objReader[i].ToString(), out k);
Другие предоставили вам решение, но почему это необходимо: свойство является просто синтаксическим сахаром для метода.
Например, когда вы объявляете свойство под названием Name
с помощью геттера и сеттера, под капотом компилятор фактически генерирует методы, называемые get_Name()
и set_Name(value)
. Затем, когда вы читаете и записываете это свойство, компилятор переводит эти операции в вызовы этих сгенерированных методов.
Когда вы это рассматриваете, становится очевидным, почему вы не можете передать свойство в качестве выходного параметра - вы действительно должны передавать ссылку на метод, а не ссылку на объект a переменная, которую ожидает выходной параметр.
Аналогичный случай существует для индексаторов.
Это случайная абстракция. Свойством на самом деле является метод, 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 "заставляет работать, если вы можете".
Поместите параметр out в локальную переменную, а затем установите переменную в bd.Budget
:
double tempVar = 0.0;
if (double.TryParse(objReader[i].ToString(), out tempVar))
{
bd.Budget = tempVar;
}
Обновление: прямо из MSDN:
Свойства не являются переменными и поэтому не могут быть переданы как параметры.
Возможно интересный - вы можете написать свой собственный:
//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.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;
Итак, бюджет - это свойство, правильно?
Скорее сначала установите его на локальную переменную, а затем установите для него значение свойства.
double t = 0;
double.TryParse(objReader[i].ToString(), out t);
bd.Budget = t;