developer tip

속성 또는 인덱서는 out 또는 ref 매개 변수로 전달 될 수 없습니다.

copycodes 2020. 10. 25. 12:28
반응형

속성 또는 인덱서는 out 또는 ref 매개 변수로 전달 될 수 없습니다.


위의 오류가 발생하여 해결할 수 없습니다. 나는 조금 봤지만 그것을 제거 할 수 없습니다.

대본:

속성이 double 유형 인 budget 인 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); 

다른 사람들은 당신에게 해결책을 주었지만 이것이 왜 필요한지에 관해서는 : 속성은 메소드에 대한 구문상의 설탕 일뿐 입니다.

예를 들어 Namegetter 및 setter를 사용하여 호출 된 속성을 선언 할 때 내부적으로 컴파일러는 실제로 get_Name()and 라는 메서드를 생성합니다 set_Name(value). 그런 다음이 속성에서 읽고 쓸 때 컴파일러는 이러한 작업을 생성 된 메서드에 대한 호출로 변환합니다.

이것을 고려하면 속성을 출력 매개 변수로 전달할 수없는 이유가 분명해집니다. 실제로 출력 매개 변수가 예상 하는 변수객체에 대한 참조가 아니라 메서드에 대한 참조를 전달하는 입니다.

인덱서에도 유사한 경우가 있습니다.


이것은 유출 된 추상화의 경우입니다. 속성은 실제로 메서드이며 인덱서 getset 접근자는 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 #으로 표현 된 Run 메서드에 대해 다음 코드를 자동으로 생성하여이 문제를 해결합니다.

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

또한 사용할 수있는 해결 방법입니다. C # 팀이 동일한 접근 방식을 사용하지 않은 이유가 확실하지 않습니다. 잠재적으로 값 비싼 getter 및 setter 호출을 숨기고 싶지 않았기 때문일 수 있습니다. 또는 setter에 속성 값을 변경하는 부작용이있을 때 얻을 수있는 완전히 진단 할 수없는 동작은 할당 후에 사라집니다. C #과 VB.NET의 고전적인 차이점, C #은 "놀라운 일이 아닙니다", VB.NET은 "가능하면 작동하도록하십시오"입니다.


관심이있을 수 있습니다. 직접 작성할 수 있습니다.

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

out 매개 변수를 지역 변수에 배치 한 다음 변수를 다음과 같이 설정합니다 bd.Budget.

double tempVar = 0.0;

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

업데이트 : MSDN에서 직접 :

Properties are not variables and therefore cannot be passed as out parameters.


This is a very old post, but I'm ammending the accepted, because there is an even more convienient way of doing this which I didn't know.

It's called inline declaration and might have always been available (as in using statements) or it might have been added with C#6.0 or C#7.0 for such cases, not sure, but works like a charm anyway:

Inetad of this

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

use this:

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

So Budget is a property, correct?

Rather first set it to a local variable, and then set the property value to that.

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

참고URL : https://stackoverflow.com/questions/4518956/a-property-or-indexer-may-not-be-passed-as-an-out-or-ref-parameter

반응형