문제

지금까지 내가 이해하는 것은 다음과 같습니다.

가치로 통과하십시오

가치를 통과하면 인수 사본이 통과됩니다. 해당 사본의 변경 사항은 원본을 변경하지 않습니다.

참조로 통과하십시오

참조로 통과하면 원본에 대한 참조가 전달됩니다. 참조 변경은 원본에 영향을 미칩니다.

참조 키워드

REF는 컴파일러에 함수를 입력하기 전에 객체가 초기화되었다고 알려줍니다. ref는 값이 이미 설정되어 있음을 의미하므로 메소드가 읽고 수정할 수 있습니다. 심판은 안팎에서 두 가지 방법입니다.

키워드 밖

Out은 컴파일러에게 객체가 함수 내부에서 집중 될 것이라고 알려줍니다. out은 값이 아직 설정되지 않았으므로 반품을 호출하기 전에 설정해야합니다. 아웃은 단지 한 가지 방법 일뿐입니다.

의문

따라서 어떤 시나리오에서 Ref 및 Out Keywords의 사용과 참조로 전달되거나 가치가 전달되는 것과 결합 하시겠습니까? 예는 엄청나게 도움이 될 것입니다.

대단히 감사합니다.

도움이 되었습니까?

해결책

당신은 할 것입니다 절대 결합시키다 ref 그리고 out 1 파라미터에서. 둘 다 '참조로 패스'를 의미합니다.

물론 하나의 방법으로 Ref 매개 변수와 아웃 매개 변수를 결합 할 수 있습니다.

차이 ref 그리고 out 주로 있습니다 의지. REF 신호 신호 2 방향 데이터 전송은 1- 웨이를 의미합니다.

그러나 의도 외에도 C# 컴파일러는 명확한 할당을 추적하여 가장 눈에 띄는 차이를 만듭니다. 또한 OUT 매개 변수의 오용 (읽기)을 방지합니다.

void SetOne(out int x) 
{
  int y = x + 1; // error, 'x' not definitely assigned.
  x = 1;         // mandatory to assign something
}

void AddTwo(ref int x)
{
    x = x + 2;  // OK, x  is known to be assigned
}

void Main()
{
    int foo, bar;

    SetOne(out foo); // OK, foo does not have to be assigned
    AddTwo(ref foo); // OK, foo assigned by SetOne
    AddTwo(ref bar); // error, bar is unassigned
}

다른 팁

대단히 감사합니다

당신의 이해는 언어를 정확하고 신중하게 사용함으로써 개선 될 것입니다.

가치를 통과하면 인수 사본이 통과됩니다.

예, 이것은 정확합니다.

해당 사본의 변경 사항은 원본을 변경하지 않습니다.

정확히. 주의 깊게 구별하여 시작하십시오 가치 그리고 변수. 고려하다:

class Foo { public int x; }
...
void N() 
{
  Foo blah = new Foo();
  blah.x = 0;
  M(blah);
}
...
void M(Foo foo)
{
  foo.x = 123; // changes blah.x
  foo = null; // does not change blah
}

여기의 변수는 x, blah 및 foo입니다. X는 필드이고 Blah는 로컬이며 Foo는 공식 매개 변수입니다.

여기의 값은 NULL, 0, 123이며 FOO 인스턴스에 대한 참조입니다. 그 참조는 가치입니다. 이 사실을 이해하는 것이 중요합니다.

blah의 값의 사본은 변수 blah의 값을 변수 foo로 복사하여 전달됩니다. Blah의 가치는 Foo의 인스턴스에 대한 참조입니다.

m은 blah 값의 사본을 가지고 있기 때문에 변수 x의 값을 변경할 수 있습니다. 이는 foo에 대한 참조입니다. m이 foo의 내용을 null로 바꿀 때, 그것은 blah를 바꾸지 않습니다. Foo에는 Blah의 가치 사본이 포함되어 있습니다.

참조로 통과하면 원본에 대한 참조가 전달됩니다.

문구를주의 깊게 선택하십시오. "원본"은 무엇입니까?

이것은 "가변이어야하는 인수에 대한 언급이 통과된다는 것을 참조로 통과하는 것이 더 잘 언급 될 것입니다. 더 쉬운 방법은 "참조로 전달하면 매개 변수를 인수로 전달한 변수의 별칭으로 만듭니다"라는 것입니다.

참조 변경은 원본에 영향을 미칩니다.

매개 변수와 인수는 서로에 대한 별칭이기 때문에 참조의 변경이 원본에 영향을 미치는 것은 아닙니다. 참조는 원본입니다. 그들은 둘 다 동일한 변수.

REF는 컴파일러에 함수를 입력하기 전에 객체가 초기화되었다고 알려줍니다.

"대상"은 의미가 없습니다. 당신은 "변수"를 의미합니다.

"Ref"는 컴파일러에 변수가 초기화되었다고 말하지 않습니다. 오히려, "Ref"는 컴파일러에게 "컴파일러가 변수가 초기화되었는지 확인해야한다"고 말합니다. 다소 다릅니다!

ref는 값이 이미 설정되었음을 의미합니다.

아니요, 심판은 변하기 쉬운 이미 설정되었습니다. "가치 설정"과 같은 것은 없습니다.

따라서이 방법은 읽고 수정할 수 있습니다.

"IT"는 "변수"를 의미합니다.

심판은 안팎에서 두 가지 방법입니다.

옳은.

Out은 컴파일러에게 객체가 함수 내부에서 집중 될 것이라고 알려줍니다.

"변수"를 의미하는 "객체"사용을 중지하십시오. 완전히 다른 것들을 혼동하지 않으면 물건을 훨씬 더 명확하게 이해할 것입니다. 변수는 객체가 아닙니다. 변수입니다 스토리지 위치 그 중 일부는 포함 할 수 있습니다 가치, 그리고 그 값 중 일부는 그럴 수 있습니다 개체에 대한 참조.

따라서 Out은 컴파일러에게 변수가 메소드 내부에서 초기화 될 것이라고 말하지만 그렇습니다. 방법이 예외를 던지거나 방법이 무한 루프로 들어가는 경우를 잊고 있습니다. 이는 또한 법적 시나리오이기도합니다.

아웃은 값이 아직 설정되지 않았 음을 의미합니다.

다시, "값"에 의해, 당신은 "변수"를 의미합니다. 그러나 이것은 정확하지 않습니다. 초기화 된 변수를 "아웃"매개 변수로 전달하는 것은 완벽하게 합법적입니다. 무의미하지만 합법적입니다.

따라서 반품을 호출하기 전에 설정해야합니다.

"반환"은 호출되지 않습니다. 방법이 호출됩니다. 그러나 예, 메소드는 정상적으로 반환하기 전에 변수에 값을 할당해야합니다.

아웃은 단지 한 가지 방법 일뿐입니다.

오른쪽.

그래서 어떤 시나리오에서, 당신은 심판과 출력 키워드의 사용을 결합 하시겠습니까?

그러한 시나리오는 없습니다.

당신은 어느 쪽이든 통과하는 역학을 이해합니다. 일부 매개 변수 시나리오는 다음과 같습니다.

  • ref int num 인/아웃 매개 변수의 경우. 함수 5월 그것의 값을 수정하십시오.
  • out int num 함수를 제외한 REF처럼 반환하기 전에 값을 할당해야합니다.

일반적으로 출력 매개 변수는 함수가 여러 값을 반환해야 할 때에 적합합니다. 함수는 하나의 리턴 값 만 가지므로 (복합적 일 수는 있지만).

때로는 일부 ado.net 방법과 마찬가지로 데이터 액세스 제공 업체가 출력 매개 변수를 사용하여 정보를 전달합니다. 일부 데이터 액세스 방법은 데이터베이스가 매개 변수를 갖는 절차를 저장 한 절차를 모방합니다.

편집하다: 참조 유형에 대한 한 가지 규정은 매개 변수입니다 ref StringBuilder word 또는 StringBuilder word (값별로) 동일하게 행동하십시오 - 외부의 문자열은 영향을 받지만, 그 시점에서 초점은 힙의 값이 아닌 초점이 기준이기 때문에 약간 다를 수 있습니다.

편집하다: C#의 'out'키워드가 당신이 기대할 수있는 일을하지 않는다는 것을 반영하기 위해이 답변을 수정했습니다 (예 : 컴퓨터 과학 용어의 진정한 아웃 매개 변수). 나는 원래 'out'은 가치에 따라 패스되었지만 잘못된 것으로 판명되었다고 말했습니다.

함께 'out'과 'ref'를 함께 사용할 수 없습니다. C# (Net Framework)에는 세 가지 전화 규칙이 있습니다.

  • 키워드 없음 = 값에 따라 (in)
  • 'out'keyword = 통화 전에 명확한 할당 요구 사항이없는 참조 (참조) 통과
  • 'ref'keyword = 통화 전에 명확한 할당 요구 사항이있는 참조 (Ref)에 의해 통과

C#에는 진정한 아웃 또는 아웃 매개 변수 능력이 없습니다.

C#의 'out'매개 변수가 실제 매개 변수가 아닌 것을 보려면 다음 코드를 사용할 수 있습니다.

  public class Test
  {
    Action _showValue;

    public void Run()
    {
      string local = "Initial";
      _showValue = () => { Console.WriteLine(local.ToString()); };

      Console.WriteLine("Passing by value");
      inMethod(local);

      Console.WriteLine("Passing by reference with 'out' keyword");
      outMethod(out local);

      Console.WriteLine("Passing by reference with 'ref' keyword");
      refMethod(ref local);

    }

    void inMethod(string arg)
    {
      _showValue();
      arg = "IN";
      _showValue();
    }

    void outMethod(out string arg)
    {
      _showValue();
      arg = "OUT";
      _showValue();
    }

    void refMethod(ref string arg)
    {
      _showValue();
      arg = "REF";
      _showValue();
    }
  }

출력은 다음과 같습니다.

Passing by value
Initial
Initial
Passing by reference with 'out' keyword
Initial
OUT
Passing by reference with 'ref' keyword
OUT
REF

보시다시피, 'out'과 'ref'는 실제로 참조를 통과합니다. 유일한 차이점은 컴파일러가 명확한 할당 목적으로 처리하는 방법에 있습니다.

사용 OUT 키워드는 둘 이상의 값을 반환 해야하는 메소드가있는 경우 유용합니다. 예를 들어, 같은 방법을 살펴보십시오 int.TryParse().

사용 REF 대상의 명시성을위한 것입니다. 메소드에 전달 된 비-프리맨 인은 본질적으로 참조로 전달된다는 점을 명심해야합니다. 정상적인 관리 코드에는 필요하지 않습니다. REF 키워드를 선언하면 매개 변수가 메소드 본문에서 수정 될 가능성이 높아서 호출 코드가이를 알아야한다고 명시하고 있습니다 (따라서 명시 적으로 추가 해야하는 이유 ref 호출 코드에서도.

C ++를 이해하면 도움이 될 것입니다.

void Foo(Bar) {} // pass by value c# (if it's a value type ;))
void Foo(Bar) {} // c++

void Foo(Bar) {} // pass by reference c# (if it's a reference type ;))
void Foo(Bar&) {} // c++

void Foo(ref Bar) {} // c#
void Foo(Bar*) // c++

void Foo(out Bar) {} // c#
void Foo(Bar**) {} // c++ (the contents of *Bar needs to be filled up)

당신은 다른 함수에 의해 읽고 쓰고 싶은 것을 Ref로지나갑니다. 따라서 올바르게 읽으려면 초기화 된 변수를 전달해야합니다.

편집 : 예 :

void mymethod(ref int a) {
  a++;
}

다른 함수에 의해 작성하려는 무언가를 전달하지만, 기능에 의해 읽지 않으므로 작성할 필요는 없습니다.

편집 : 예 :

void mymethod2(out string a) {
  a="hello";
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top