문제

Byref와 Byval 중에서 선택할 때 고려해야 할 사항은 무엇입니까?

나는 둘 사이의 차이점을 이해하지만 Byref가 자원을 저장하거나 .NET 환경에서이를 걱정 해야하는지 완전히 이해하지 못합니다.

상황에서 기능이 중요하지 않은 경우 둘을 어떻게 결정합니까?

도움이 되었습니까?

해결책

이것에 대해 많은 잘못된 정보가 있습니다. 가장 중요한 것은 당신이 이해한다는 것입니다 값 유형과 참조 유형의 차이, 그리고 통과별로의 차이와 참조 별 패스.

당신은 거의 항상 가치를 통과하고 싶어합니다. 참조로 통과하는 것은 거의 항상 "전달 된 목록에 물건을 추가하는 것이 아니라 하나 이상의 결과를 반환하고 싶습니다." Pass-by-Reference를 사용하는 방법의 전형적인 예는 다음과 같습니다 int32.tryparse 여기서 반환 값은 성공/실패이며, 구문 분석 된 값은 Out 매개 변수에 의해 "반환"됩니다.

다른 팁

기본값은 모든 유형의 경우 ByValue이지만 값 유형과 달리 "참조 유형"(클래스)의 두 옵션이 무엇을 의미하는지 이해하는 것이 중요합니다. (구조).

참조 유형의 경우 메소드에서 참조 유형 변수를 선언하면 해당 변수는 메소드 스택 프레임의 메모리 위치입니다. 힙에 없습니다. 해당 변수를 초기화하면 (새 또는 공장을 사용하여) 힙에 실제 객체를 생성하고 해당 객체의 주소는 메서드 스택 프레임에 선언 된 참조 변수에 저장됩니다.

기준 유형을 다른 메소드 Byval로 전달하면 호출 메소드 스택에 저장된 주소의 사본을 작성하고 해당 값 (포인터 주소)의 사본을 호출 메소드로 전달합니다. 여기서 새 메모리에 저장됩니다. 호출 된 메소드 스택의 슬롯. 호출 된 방법 내부에서 새로운 복제 된 변수는 힙의 동일한 객체를 직접 지적합니다. 따라서 사용하면 동일한 객체의 속성이 변경 될 수 있습니다. 그러나 원래 참조 변수 (호출 메소드 스택에서)를 가리키는 힙 객체를 변경할 수 없습니다. 호출 된 방법에서 내가 쓴 경우

  myVar = new object();

호출 방법의 원래 변수는 새 객체를 가리 키도록 변경되지 않았습니다.

참조 유형 BYREF, OTOH를 통과하면 호출 메소드 스택의 선언 된 변수에 대한 포인터를 전달하고 있습니다 (힙의 객체에 대한 포인터가 포함되어 있음). 호출 메소드 스택의 메모리 위치를 가리 킵니다.
이제 호출 메소드의 변수에 대한 "심판"이기 때문에 호출 메소드에서 변수의 값을 변경하면 호출 방법의 변수에 대한 "심판"이므로 실제로 어떤 개체를 변경하고 있습니다. 호출 방법의 변수가 가리키고 있습니다. 따라서 호출 된 메소드가 반환 된 후, 호출 방법의 변수는 더 이상 힙의 동일한 원본 객체를 가리키지 않습니다.

Byval은 "기본값"이어야합니다. Byref를 사용해야 할 특정 이유가 없으면 사용하십시오.

.NET에 ByVal을 전달하면 객체의 사본을 만들지 않으며 더 많은 리소스를 소비하지 않으면 Byref, 포인터는 여전히 함수로 전달됩니다. 런타임은 기능에서 포인터를 수정할 수 없도록하고 다른 값을 반환 할 수 있도록합니다. 객체 내의 값을 변경할 수 있으며 함수 외부의 변경 사항이 표시됩니다. 그렇기 때문에 Byref가 거의 사용되지 않는 이유입니다. 다시 나오는 실제 객체를 변경하기 위해 함수를 원할 때만 필요합니다. 따라서 출력 매개 변수입니다.

매개 변수가 "출력"매개 변수 인 경우에만 "byref"를 사용하십시오. 그렇지 않으면 "byval"을 사용하십시오. 명시 적으로 값을 반환해서는 안되는 매개 변수에서 "byref"를 사용하는 것은 위험하고 버그를 쉽게 생성 할 수 있습니다.

나는 Byref가 절대 사용해서는 안된다고 주장합니다. 기능이 여러 값 (ByRef 매개 변수를 통해)을 반환 할 수있는 일반적인 사용 사례에도 적용합니다. 기능이 다중 반환 값을 포함하는 구조화 된 응답을 반환하는 것이 좋습니다. 함수가 리턴 명령문을 통해서만 값을 반환하는 경우 더 명확하고 분명합니다.

특정 인수를 BYREF로 표시하면 기능의 사용자가 변하기 쉬운 그 주장에 할당 **가 수정 될 것입니다. ****

Byref를 사용하는 경우 모든 Args의 경우 함수에 의해 어떤 변수가 수정되었는지, 어떤 변수가 읽는 지 알 수있는 방법이 없습니다. (함수 소스 내부를 들여다 보는 것 외에!)

Microsoft에 따르면 Byval 또는 Byref를 선택하면 충분히 큰 값에 대한 성능에 영향을 줄 수 있습니다 ( 가치와 참조별로 인수 전달 (Visual Basic)):

성능. 통과 메커니즘이 코드의 성능에 영향을 줄 수 있지만, 차이는 일반적으로 중요하지 않습니다. 이것에 대한 한 가지 예외는 ByVal이 통과 한 값 유형입니다. 이 경우 Visual Basic은 인수의 전체 데이터 내용을 복사합니다. 그러므로, 큰 가치를 위해 구조와 같은 유형, 더 효율적일 수 있습니다 Byref를 통과합니다.

강조 추가].

Sub last_column_process()
Dim last_column As Integer

last_column = 234
MsgBox last_column

trying_byref x:=last_column
MsgBox last_column

trying_byval v:=last_column
MsgBox last_column

End Sub

Sub trying_byref(ByRef x)
x = 345
End Sub

Sub trying_byval(ByRef v)
v = 555
End Sub

많은 혼란이 단순화하려고 노력할 것입니다. 기본적으로 4 가지 선택이 있습니다.

  1. 값 유형 ByVal을 통과하십시오
  2. 값 유형 Byref를 통과하십시오
  3. 객체를 통과하십시오
  4. 객체 Byref를 통과하십시오

어떤 사람들은 당신이해야한다고 말합니다 절대 Byref를 사용하십시오. 기술적으로 정확하지만 한 가지는 확실합니다. 당신은해야합니다 절대 단어를 사용하십시오 절대. 처음부터 시스템을 설계하는 경우 Byref는 모든 비용으로 피해야합니다. 그것을 사용하면 설계 결함이 노출됩니다. 그러나 기존 시스템에서 작업하면 좋은 디자인을 구현할 수있는 융통성을 제공하지 못할 수 있습니다. 때로는 Byref를 사용하여 동의해야합니다. 예를 들어 Byref를 사용하여 2 일 안에 완료를 할 수 있다면 바퀴를 재발 명하고 Byref 사용을 피하기 위해 동일한 수정을 얻기 위해 일주일이 걸리는 것이 바람직 할 수 있습니다.

요약:

  1. 값 유형에서 ByVal 사용 : 값을 함수로 전달합니다. 이것은 기능을 디자인하는 선호하는 방법입니다.
  2. 값 유형에서 Byref 사용 : 함수에서 하나 이상의 값을 반환하는 데 유용합니다. 기존 시스템에 둘 이상의 값을 반환 해야하는 함수를 작성하는 경우 하나의 함수에 대해서만 객체 (및 속성을 설정하고 처분)하는 것보다 낫습니다.
  3. 개체에서 ByVal 사용 : 객체의 포인터를 함수로 전달합니다. 함수는 객체를 수정할 수 있습니다.
  4. 객체에서 Byref 사용 : 기능에 대한 개체의 포인터에 포인터를 전달합니다. 발신자가 가리키는 객체를 변경할 수 있습니다. 이것은 약간의 버그를 찾기가 어려울 수 있으며 그것을 사용해야할만한 충분한 이유를 생각할 수 없습니다. 하나가 없다는 것을 의미하지는 않지만, 그 사이에는 거의 없다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top