C # 속성 및 참조 매개 변수, 왜 설탕이 없습니까?
C #에서 작업하는 동안이 오류 메시지를 보았습니다.
속성 또는 인덱서는 out 또는 ref 매개 변수로 전달 될 수 없습니다.
이 문제의 원인을 알고 올바른 유형의 지역 변수를 만들고 out
/ ref
매개 변수 로 함수를 호출 한 다음 속성에 다시 할당 하는 빠른 솔루션 을 수행했습니다.
RefFn(ref obj.prop);
로 변하다
{
var t = obj.prop;
RefFn(ref t);
obj.prop = t;
}
속성이 현재 컨텍스트에서 get 및 set을 지원하지 않으면 분명히 실패합니다.
왜 C #이 나를 위해 그렇게하지 않습니까?
이것이 문제를 일으킬 수있는 유일한 경우는 다음과 같습니다.
- 스레딩
- 예외
스레딩의 경우 해당 변환은 쓰기가 발생하는시기 (함수 호출 후 대 함수 호출에서)에 영향을 주지만, 그에 의존하는 코드는 중단 될 때 약간의 동정을받을 것이라고 생각합니다.
예외의 경우 우려 사항은 다음과 같습니다. 함수 ref
가 throw보다 여러 매개 변수 중 하나에 할당하면 어떻게됩니까 ? 사소한 솔루션은 일부는 지정해야하고 일부는 지정하지 않아야 할 때 매개 변수를 모두 지정하거나 지정하지 않습니다. 다시 말하지만 이것이 언어 사용이 지원 될 것이라고 생각하지 않습니다.
참고 :이 오류 메시지가 생성되는 이유를 이해합니다. 내가 찾고있는 것은 C #이 사소한 해결 방법을 자동으로 구현하지 않는 이유에 대한 근거입니다.
그냥 정보를 원하시면, C # 4.0 것입니다 뭔가가 같은 이 설탕을하지만, 방법 Interop를 호출하는 경우에만 - 부분적으로의 깎아 지른듯한 성향에 ref
이 시나리오한다. 나는 그것을 많이 테스트하지 않았다 (CTP에서); 우리는 그것이 어떻게 풀리는 지 봐야 할 것입니다 ...
실제로 메서드 호출의 결과 인 인덱서 의 결과 를 전달하기 때문 입니다. 인덱서 속성에도 setter가 있다는 보장은 없으며이를 ref로 전달하면 setter가 호출되지 않고 속성이 설정 될 것이라고 생각할 때 개발자가 잘못된 보안으로 이어질 수 있습니다.
보다 기술적 인 수준에서 ref 및 out은 전달 된 객체의 메모리 주소를 전달하고 속성을 설정하려면 setter를 호출해야하므로 속성 유형이 다음과 같을 때 속성이 실제로 변경 될 것이라는 보장은 없습니다. 불변. ref 및 out은 메서드 반환시 값을 설정 하는 것이 아니라 실제 메모리 참조를 개체 자체에 전달합니다.
속성은 Java 스타일 getX / setX 메서드에 대한 구문 설탕에 지나지 않습니다. 메서드의 'ref'에는별로 의미가 없습니다. 귀하의 경우에는 속성이 단순히 필드를 스터 빙하기 때문에 의미가 있습니다. 속성은 스텁 일 필요가 없으므로 프레임 워크는 속성에서 'ref'를 허용 할 수 없습니다.
편집 : 글쎄, 간단한 대답은 속성 getter 또는 setter가 필드 읽기 / 쓰기보다 훨씬 더 많은 것을 포함 할 수 있다는 단순한 사실로 인해 예상치 못한 것은 말할 것도없고 제안하는 설탕의 종류를 허용하는 것이 바람직하지 않다는 것입니다. 이것은 내가 이전에이 기능이 필요하지 않았다는 말이 아니라, 그들이 제공하고 싶어하지 않는 이유를 이해한다는 것뿐입니다.
ref
/ 와 함께 필드를 사용할 수 out
있지만 속성 은 사용할 수 없습니다. 그 이유는 속성은 실제로 특수 메서드의 구문 바로 가기에 불과하기 때문입니다. CLR은 속성을 즉각적으로 지원하지 않으므로 컴파일러는 실제로 get / set 속성을 해당 get_X
및 set_X
메서드로 변환 합니다.
스레드로부터 안전하지 않습니다. 두 스레드가 동시에 속성 값의 자체 복사본을 만들고이를 ref 매개 변수로 함수에 전달하면 그중 하나만 속성으로 돌아갑니다.
class Program
{
static int PropertyX { get; set; }
static void Main()
{
PropertyX = 0;
// Sugared from:
// WaitCallback w = (o) => WaitAndIncrement(500, ref PropertyX);
WaitCallback w = (o) => {
int x1 = PropertyX;
WaitAndIncrement(500, ref x1);
PropertyX = x1;
};
// end sugar
ThreadPool.QueueUserWorkItem(w);
// Sugared from:
// WaitAndIncrement(1000, ref PropertyX);
int x2 = PropertyX;
WaitAndIncrement(1000, ref x2);
PropertyX = x2;
// end sugar
Console.WriteLine(PropertyX);
}
static void WaitAndIncrement(int wait, ref int i)
{
Thread.Sleep(wait);
i++;
}
}
PropertyX는 1로 끝나는 반면 필드 또는 지역 변수는 2가됩니다.
이 코드 샘플은 또한 컴파일러에게 설탕 같은 작업을 요청할 때 익명 메서드와 같은 문제로 인해 발생하는 어려움을 강조합니다.
The reason for this is that C# does not support "parameterful" properties that accept parameters passed by reference. It is interesting to note that the CLR does support this functionalty but C# does not.
When you pass ref/out prepended it means that you are passing a reference type which is stored in the heap.
Properties are wrapper methods, not variables.
If you're asking why the compiler doesn't substitute the field returned by the property's getter, it's because the getter can return a const or readonly or literal or something else that shouldn't be re-initialized or overwritten.
This site appears to have a work around for you. I have not tested it though, so I can't guarantee it will work. The example appears to use reflection in order to gain access to the get and set functions of the property. This is probably not a recommended approach, but it might accomplish what you're asking for.
http://www.codeproject.com/KB/cs/Passing_Properties_byref.aspx
참고URL : https://stackoverflow.com/questions/529782/c-sharp-property-and-ref-parameter-why-no-sugar
'code' 카테고리의 다른 글
.cer 및 pfx 파일의 차이점은 무엇입니까 (0) | 2020.11.02 |
---|---|
flatMap () 후 filter ()가 Java 스트림에서 "완전히"게으르지 않은 이유는 무엇입니까? (0) | 2020.11.02 |
요소 높이와 너비를 기준으로 X 및 Y 백분율 값을 번역 하시겠습니까? (0) | 2020.11.02 |
> &는 무엇을 의미합니까? (0) | 2020.11.02 |
iOS 앱 충돌, 디버깅 할 때 xcode에서 'X의 iPhone 연결이 끊어졌습니다'라고 표시됨 (0) | 2020.11.02 |