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

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

сценарий:

у меня есть класс 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);

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

6 ответов


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

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

заменить bd.Бюджет с некоторой переменной.

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

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

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

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

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


Это случай протекающей абстракции. Свойство на самом деле является методом get и set аксессоры для индексатора компилируются в методы 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 компилятор решает это, автоматически генерируя этот код для запуска метод, выраженный в C#:

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

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


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

double tempVar = 0.0;

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

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

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

http://msdn.microsoft.com/en-us/library/t3c3bfhx (v=против 80).aspx


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

    //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;
}

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

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

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