다른 사람이 지적했듯이 "ref to variable"유형의 필드를 가질 수 없습니다. 그러나 당신이 그것을 할 수 없다는 것을 아는 것은 아마도 불만족 스러울 것입니다; 당신은 아마 또한 첫 번째, 왜, 그리고 두 번째,이 제한을 극복하는 방법을 알고 싶다.
이유 이유는 단지 세 가지 가능성이 있기 때문에입니다 :
1) REF 유형의 안전하지 않은 필드
3) 임시 저장소를 사용하지 마십시오 허용
2) 심판 유형의 필드를 허용 안가 지역 변수를위한 풀 (일명 "스택")
ref 타입의 필드를 허용한다고 가정 해 봅시다. 그럼 당신은 할 수있어
public ref int x;
void M()
{
int y = 123;
this.x = ref y;
}
M
완료 후 y를 액세스 할 수 있습니다. 즉, y에 대한 저장 공간이 더 이상 존재하지 않기 때문에 (2) - this.x
에 액세스하면 크래시가 발생하고 끔찍하게 죽을 수도 있습니다. 또는 우리는 (3)의 경우이므로 로컬 y
이 가비지에 저장됩니다 임시 메모리 풀이 아니라 수집 된 힙.
지역 변수가 ref로 전달되는 경우에도 로컬 변수가 임시 풀에 저장되는 최적화가 마음에 들지만 프로그램을 중단하고 나중에 죽일 수있는 시간 폭탄을 남길 수 있다는 생각이 싫습니다. 따라서 옵션 1 : ref 필드가 없습니다.
익명 함수의 폐쇄 변수 인 지역 변수에 대해서는 옵션 (3)을 선택합니다. 이러한 로컬 변수는 임시 풀에서 할당되지 않습니다.
그런 다음 두 번째 질문으로 안내합니다. 어떻게 해결할 수 있습니까? ref 필드가 다른 변수의 getter와 setter를 만드는 것이면 완벽하게 합법적입니다.
sealed class Ref<T>
{
private readonly Func<T> getter;
private readonly Action<T> setter;
public Ref(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value { get { return getter(); } set { setter(value); } }
}
...
Ref<int> x;
void M()
{
int y = 123;
x = new Ref<int>(()=>y, z=>{y=z;});
x.Value = 456;
Console.WriteLine(y); // 456 -- setting x.Value changes y.
}
그리고 거기에 가야합니다. y
은 gc 힙에 저장되고 x
은 y
을 가져오고 설정할 수있는 개체입니다.
CLR은 참조 지역과 참조 반환 방법을 지원하지만 C#은 지원하지 않습니다. 아마도 C#의 가상 버전이 이러한 기능을 지원할 것입니다. 프로토 타입을 작성 했으므로 제대로 작동합니다. 그러나 이것은 우선 순위 목록에 실재하지 않습니다. 그래서 저는 희망을 갖지 않을 것입니다.
업데이트 : 위의 단락에서 언급 한 기능이 C# 7에서 실제로 구현되었습니다. 그러나 여전히 필드에는 ref를 저장할 수 없습니다.
두 번째 단락을 약간 확장 하시겠습니까? "더 큰 변경 가능 객체"는 완전히 명확하지 않습니다. 또한 필드에서 문자열 참조를 유지할 방법이 없다면 StringWrapper가 어떻게 작동합니까? –
나는 명확히해야 할 예를 제시했다. 제가 말했듯이, 실제 디자인에서 StringWrapper는 단순한 문자열 이상을 담고있는 비즈니스 객체 일 것입니다. –
아이디어를 제공해 주셔서 감사합니다. 내 예제는 실제로 단순화 된 것입니다. 왜냐하면 실제로 참조 할 수 있도록 할당하려고하는 실제 코드에 객체 (문자열이 아님)가 있기 때문입니다. 내가 찾고있는 동작은 객체의 사용자가 객체에 null을 할당 할 수 있도록 허용하거나 객체의 메소드에서 해당 유형의 새 인스턴스를 할당하는 것입니다. 일부 의존성 삽입의 일부로 생성자를 통해 객체를 전달하므로 다른 메소드는 필드에 액세스하여 객체를 볼 수 있습니다. 부끄러운 일은 내가 원하는대로 할 수없는 것처럼 보입니다. – Jamie