C#의 자동 속성을 사용하기 위해 구조물 의이 ()가 호출 해야하는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/272153

문제

다음과 같은 자동 속성을 사용하여 C#의 구조물을 정의하는 경우.

public struct Address
{
    public Address(string line1, string line2, string city, string state, string zip)
    {
        Line1 = line1;
        Line2 = line2;
        City = city;
        State = state;
        Zip = zip;
    }

    public string Line1 { get; protected set; }
    public string Line2 { get; protected set; }
    public string City { get; protected set; }
    public string State { get; protected set; }
    public string Zip { get; protected set; }
}

파일을 작성하려고하면 컴파일 오류가 발생합니다. The 'this' object cannot be used before all of its fields are assigned to. 이는 생성자를 변경하여 다음과 같이 기본 생성자에게 사슬을 호출하여 해결할 수 있습니다.

public Address(string line1, string line2, string city, string state, string zip): this()
{
    Line1 = line1;
    Line2 = line2;
    City = city;
    State = state;
    Zip = zip;
}

내 질문은 왜이 일이 효과가 있고 무슨 일이 일어나고 있습니까? 나는 추측이 있고, IL을 보면서 그것을 증명하려고 노력했지만, IL을 분해 할 수 있다고 생각하면 농담입니다. 그러나 내 생각에, 자동 속성은 컴파일러가 무대 뒤에서 속성에 대한 필드를 생성함으로써 작동한다는 것입니다. 해당 필드는 코드를 통해 액세스 할 수 없습니다. 모든 설정 및 그 글리어는 속성을 통해 수행해야합니다. 구조물을 만들 때 기본 생성자를 명시 적으로 정의 할 수 없습니다. 따라서 무대 뒤에서 컴파일러는 개발자가 볼 수없는 필드 값을 설정하는 기본 생성자를 생성해야합니다.

모든 Il Wizards는 내 이론을 증명하거나 반증 할 수 있습니다.

도움이 되었습니까?

해결책

참고 : C# 6 기준으로는 필요하지 않지만 C# 6과 함께 읽기 전용 자동 구현 속성을 사용해야합니다 ... 어쨌든 ...

this() 컴파일러에 관한 한 필드가 확실히 할당되어 있는지 확인하십시오. 모든 필드를 기본값으로 설정합니다. 액세스를 시작하기 전에 완전히 구성된 구조물이 있어야합니다. 어느 속성.

짜증나지만 그게 그 방식입니다. 그래도 이것이 정말로이 구조물이되기를 원하십니까? 그리고 왜 구조물에서 보호 된 세터를 사용합니까 (파생 될 수 없음)?

다른 팁

속성은 Get 방법 및/또는 a Set 방법. CLR에는 특정 방법이 특성으로 간주되어야 함을 나타내는 메타 데이터가 있으며, 이는 컴파일러가 방법으로 허용하지 않는 일부 구성을 허용해야합니다. 예를 들어, if X 읽기 쓰기 속성입니다 Foo, 컴파일러가 번역됩니다 Foo.X += 5 ~ 안으로 Foo.SET_X_METHOD(Foo.GET_X_METHOD() + 5) (이 방법의 이름은 다르게 명명되었으며 일반적으로 이름으로 액세스 할 수 없습니다).

자가 프로페티는 속성 외부의 코드의 관점에서 필드와 같은 방식으로 행동하는 방식으로 개인 필드에 액세스하는 한 쌍의 get/set 메소드를 구현하지만, 자동 프로페티는 한 쌍의 get/입니다. 다른 속성과 마찬가지로 메소드를 설정하십시오. 결과적으로, 같은 진술 Foo.X = 5; 번역됩니다 Foo.SET_X_METHOD(5). C# Compiler는 메소드 호출로 단지 확인하고 메소드가 읽거나 쓰는 필드를 나타내는 메타 데이터가 포함되어 있지 않기 때문에 컴파일러는 모든 필드의 모든 필드를 모르는 경우 방법 호출을 금지합니다. Foo 작성되었습니다.

개인적으로, 저의 조언은 구조 유형과 함께 자동 요금을 사용하는 것을 피하는 것입니다. AutoProperties는 클래스 속성이 업데이트 알림과 같은 기능을 지원할 수 있으므로 클래스에 적합합니다. 초기 버전의 클래스가 업데이트 알림을 지원하지 않더라도 해당 버전이 필드가 아닌 자동 인물을 사용하면 향후 버전이 클래스 소비자를 재 작업 할 필요없이 업데이트 통지 기능을 추가 할 수 있음을 의미합니다. 그러나 구조는 필드와 같은 특성에 추가하고자하는 대부분의 기능 유형을 의미있게 지원할 수 없습니다.

또한, 필드와 속성 사이의 성능 차이는 클래스 유형보다 큰 구조에서 훨씬 더 큽니다. 실제로, 큰 구조를 피하기위한 많은 권장 사항은 이러한 차이의 결과입니다. 불필요하게 복사하는 것을 피하면 큰 구조가 실제로 매우 효율적일 수 있습니다. 거대한 구조를 가지고 있더라도 HexDecet<HexDecet<HexDecet<Integer>>>, 어디 HexDecet<T> 노출 된 필드가 포함되어 있습니다 F0..F15 유형의 T, 같은 진술 Foo = MyThing.F3.F6.F9; 단순히 하나의 정수를 읽어야합니다 MyThing 그리고 그것을 보관합니다 Foo, 일지라도 MyThing 구조물 표준 (16K를 차지하는 4096 정수)에 의해 거대합니다. 또한 그 요소를 매우 쉽게 업데이트 할 수 있습니다. MyThing.F3.F6.F9 += 26;. 대조적으로, if F0..F15 자동 비판이었다 Foo = MyThing.F3.F6.F9 1k의 데이터를 복사해야합니다 MyThing.F3 임시로 (전화하십시오 temp1, 그런 다음 64 바이트의 데이터 temp1.F6 에게 temp2) 마침내 4 바이트의 데이터를 읽기 전에 temp2.F9. ick. 더 나쁜 것은 MyThing.F3.F6.F9 같은 것이 필요합니다 var t1 = MyThing.F3; var t2 = t1.F6; t2.F9 += 26; t1.F6 = f2; MyThing.F3 = t1;.

"돌연변이 가능한 구조 유형"에 대한 오랜 불만은 실제로 읽기/쓰기 속성이있는 구조 유형에 대한 불만입니다. 속성을 필드로 바꾸면 문제가 사라집니다.

추신 : 속성이 참조를 보유하는 클래스 객체에 액세스하는 구조를 갖는 것이 유용 할 수 있습니다. 예를 들어, 버전을 갖는 것이 좋을 것입니다. ArraySegment<T> 말할 수있는 수업 Var foo[] = new int[100]; Var MyArrSeg = New ArraySegment<int>(foo, 25, 25); MyArrSeg[6] += 9;, 마지막 진술이 9에 9를 추가하도록하십시오 (25+6) foo. 이전 버전의 C# One에서는 그렇게 할 수 있습니다. 불행히도, 필드가 더 적절한 프레임 워크에서 자동 분류기를 자주 사용하면 컴파일러에 대한 광범위한 불만이있어 속성 세터가 읽기 전용 구조에서 쓸모 없게 호출 될 수 있습니다. 결과적으로, 속성 세터가 실제로 구조물의 모든 필드를 수정하는지 여부에 관계없이 읽기 전용 구조에서 부동산 세터를 호출하는 것이 금지됩니다. 사람들이 단순히 속성 세터를 통해 Structs를 돌연변이 할 수없는 경우 (돌연변이가 적절했을 때 필드를 직접 액세스 할 수 있음) 컴파일러는 해당 제한을 구현할 필요가 없었을 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top