C #이 참조 반환을 지원하지 않는 이유는 무엇입니까? 특별한 이유가 있습니까?

.NET은 참조 반환을 지원하지만 C #은 지원하지 않는다는 것을 읽었습니다. 특별한 이유가 있습니까? 왜 내가 다음과 같은 일을 할 수 없습니까?

static ref int Max(ref int x, ref int y)
{
  if (x > y)
    return ref x;
  else
    return ref y;
} 



답변

이 질문은 2011 년 6 월 23 일제 블로그 의 주제였습니다 . 좋은 질문 감사합니다!

C # 팀은 C # 7에서이를 고려하고 있습니다. 자세한 내용은 https://github.com/dotnet/roslyn/issues/5233 을 참조하십시오.

업데이트 :이 기능은 C # 7에 도입되었습니다!


당신이 올바른지; .NET은 변수에 대한 관리되는 참조를 반환 하는 메서드를 지원 합니다. .NET은 다른 변수에 대한 관리 참조가 포함 된 로컬 변수 도 지원 합니다. 그러나 .NET은 가비지 수집 스토리를 지나치게 복잡하게하므로 다른 변수에 대한 관리되는 참조가 포함 된 필드배열 을 지원하지 않습니다 . 또한 “변수에 대한 관리되는 참조”형식은 object로 변환 할 수 없으므로로 사용할 수 없습니다. 제네릭 형식 또는 메서드에 대한 형식 인수)

어떤 이유로 논평자 “RPM1984″는이 사실에 대한 인용을 요구했다. RPM1984 .NET의이 기능에 대한 정보는 CLI 스펙 파티션 I 섹션 8.2.1.1, “관리 포인터 및 관련 유형”을 읽으십시오.

이 두 기능을 모두 지원하는 C # 버전을 만드는 것은 전적으로 가능합니다. 그런 다음과 같은 일을 할 수 있습니다

static ref int Max(ref int x, ref int y)
{
  if (x > y)
    return ref x;
  else
    return ref y;
} 

그리고 그것을 호출

int a = 123;
int b = 456;
ref int c = ref Max(ref a, ref b);
c += 100;
Console.WriteLine(b); // 556!

나는 이러한 기능을 지원하는 C 번호의 버전을 구축하는 것이 가능하다는 것을 경험적으로 알고 내가 그렇게 때문에를 . 고급 프로그래머, 특히 관리되지 않는 C ++ 코드를 이식하는 사람들은 실제로 포인터를 사용하고 메모리를 고정시키는 데 큰 어려움을 겪지 않고 참조로 작업을 수행하는 더 많은 C ++과 같은 기능을 요구합니다. 관리되는 참조를 사용하면 가비지 수집 성능을 저하시키는 비용을 지불하지 않고도 이러한 이점을 얻을 수 있습니다.

우리는이 기능을 고려하여 실제로 다른 내부 팀에 피드백을받을 수있을 정도로 충분히 구현했습니다. 그러나 현재 우리의 연구에 따르면이 기능은 실제로 지원되는 언어 기능으로 만들기에 충분한 호소력이나 사용 사례가 충분하지 않다고 생각합니다 . 우선 순위가 높고 시간과 노력이 제한되어 있으므로이 기능을 곧 사용할 수 없습니다.

또한 제대로 수행하려면 CLR을 약간 변경해야합니다. 현재 CLR은 이러한 상황을 감지하는 검출기가 없기 때문에 환급 방법을 합법적 이지만 검증 할 수없는 것으로 취급합니다.

ref int M1(ref int x)
{
    return ref x;
}

ref int M2()
{
    int y = 123;
    return ref M1(ref y); // Trouble!
}

int M3()
{
    ref int z = ref M2();
    return z;
}

M3은 M2 로컬 변수의 내용을 반환하지만 해당 변수의 수명이 끝났습니다! 스택 안전 을 명확하게 위반 하지 않는 참조 반환의 사용을 결정하는 검출기를 작성할 수 있습니다 . 우리가 할 일은 그러한 검출기를 작성하는 것이며, 검출기가 스택 안전을 증명할 수 없다면 프로그램의 해당 부분에서 ref return을 사용할 수 없습니다. 그렇게하는 것은 엄청난 양의 개발 작업이 아니지만 테스트 팀이 실제로 모든 상황을 해결하도록하는 것은 많은 부담입니다. 기능의 비용이 현재의 이점보다 비용을 능가하지 않는 수준으로 증가시키는 것은 또 다른 일입니다.

이 기능이 왜 필요한지 설명해 주시면 감사하겠습니다 . 실제 고객이 원하는 이유에 대한 정보가 많을수록 언젠가는 제품에 정보를 제공 할 가능성이 높아집니다. 귀여운 작은 기능이며 충분한 관심이 있다면 어떻게 든 고객에게 제공 할 수 있기를 바랍니다.

(또한 관련 질문을 참조 는 C #에서 변수에 대한 참조를 반환 할 수 있습니까? 그리고 ++ 나 C와 같은 C #을 함수 내에서 참조를 사용할 수 있습니까? )


답변

값 유형에 대한 참조를 리턴하는 메소드에 대해 이야기하고 있습니다. 내가 아는 C #의 내장 예제는 값 유형의 배열 접근 자입니다.

public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

이제 해당 구조체의 배열을 만듭니다.

var points = new Point[10];
points[0].X = 1;
points[0].Y = 2;

이 경우 points[0]배열 인덱서 는 struct에 대한 참조를 반환합니다. 이와 같은 “참조 반환”동작을 갖는 고유 인덱서 를 작성하는 것은 불가능합니다 (예 : 사용자 지정 컬렉션의 경우).

나는 C # 언어를 디자인하지 않았기 때문에 그것을 지원하지 않는 모든 추론을 알지 못했지만 짧은 대답은 다음과 같습니다. 우리는 그것을하지 않고 잘 지낼 수 있습니다.


답변

당신은 항상 다음과 같은 것을 할 수 있습니다 :

public delegate void MyByRefConsumer<T>(ref T val);

public void DoSomethingWithValueType(MyByRefConsumer<int> c)
{
        int x = 2;
        c(ref x);
        //Handle potentially changed x...
}


답변

C # 7.0 은 참조 반환을 지원합니다. 여기에 내 대답을 참조 하십시오 .


답변