문제

가능한 복제 :
돌연변이가 사악한 이유는 무엇입니까?

나는 여기를 포함하여 많은 곳에서 그것을 읽을 수없는 것으로 만드는 것이 낫다는 것을 읽었습니다.

이에 대한 이유는 무엇입니까? 나는 XNA의 것과 같이 변한 Microsoft가 만든 스트러크를 많이 본다. 아마도 BCL에는 더 많은 것이있을 것입니다.

이 가이드 라인을 따르지 않는 장단점은 무엇입니까?

도움이 되었습니까?

해결책

스트러크는 표현해야합니다 가치. 값은 변하지 않습니다. 12 번은 영원합니다.

그러나 고려 :

Foo foo = new Foo(); // a mutable struct
foo.Bar = 27;
Foo foo2 = foo;
foo2.Bar = 55;

이제 foo.bar와 foo2.bar는 다르며 종종 예상치 못한 일입니다. 특히 속성과 같은 시나리오에서 (다행히도 컴파일러는 이것을 감지합니다). 컬렉션 등; 당신은 그것들을 어떻게 현명하게 돌연변이합니까?

데이터 손실은 돌연변이가있는 스트러크로 너무 쉽습니다.

다른 팁

큰 사기꾼은 상황이 당신이 기대하는 방법을 행동하지 않는다는 것입니다. 특히 돌연변이가 직접 값의 혼합과 그 안에있는 기준 유형의 혼합에서 나오는 경우.

솔직히 말해서, 나는 사람들이 뉴스 그룹에서 돌연변이 가능한 구조를 사용했을 때 사람들이 생각해 낸 모든 이상한 문제를 기억할 수 없습니다. 그러나 그 이유는 분명히 존재합니다. 돌연변이 성 구조는 문제를 일으킨다. 멀리있어.

편집 :이 주제에 대해 얼마 전에 쓴 이메일을 방금 찾았습니다. 조금만 자세히 설명합니다.

  • 철학적으로 틀 렸습니다. 구조물은 일종의 기본 가치를 나타내야합니다. 그것들은 기본적으로 불변입니다. 숫자 5를 변경하지 않습니다. 변수의 값을 5에서 6으로 변경할 수 있지만 논리적으로 값 자체를 변경하지는 않습니다.

  • 그것은 실제로 문제입니다. 그것은 많은 이상한 상황을 만듭니다. 인터페이스를 통해 변하는 경우 특히 나쁩니다. 그런 다음 박스 값을 변경하기 시작할 수 있습니다. ick. 나는 돌연변이가있는 스트러크를 사용하고 문제가 발생하기 때문에 많은 뉴스 그룹 게시물을 보았습니다. 나는 매우 이상한 linq 예제를 보았는데 List<T>.Enumerator 예를 들어 구조물입니다.

나는 (성능 임계) 프로젝트에서 자주 돌연변이를 사용하는 것 - 사본 시맨틱의 의미를 이해하기 때문에 문제가 발생하지 않습니다. 내가 알 수있는 한, 사람들이 불변의 구조를 옹호하는 주된 이유는 사람들이 ~하지 않다 그 의미가 자신을 곤경에 빠뜨릴 수 없다는 것을 이해합니다.

그것은 그렇게 끔찍한 일이 아닙니다. 그러나 우리는 실제로 구조물을 돌연변이 할 수있는 최선의 선택이되는 시간이있을 때, 우리는 지금 "복음 진리"가 될 위험에 처해 있습니다. 모든 것들과 마찬가지로 규칙에는 예외가 있습니다.

돌연변이 가능한 구조물보다 조작 할 수있는 저렴한 것은 없기 때문에 그래픽 처리 루틴과 같은 고성능 코드에서 종종 볼 수 있습니다.

불행히도 Mutable Structs는 물체와 속성과 잘 어울리지 않기 때문에 구조물 자체 대신 Stuct의 사본을 수정하기에는 너무 쉽습니다. 따라서 대부분의 코드에 적합하지 않습니다.

추후, 돌연변이 성 스트러크를 복사하는 비용을 피하기 위해, 그들은 일반적으로 배열로 저장되고 전달됩니다.

기술적 인 이유는 변이 가능한 구조입니다 나타나다 그들이 실제로하지 않는 일을 할 수있는 것. 설계 시간 시맨틱은 참조 유형과 동일하기 때문에 개발자에게는 혼란스러워집니다. 이 코드 :

public void DoSomething(MySomething something)
{
    something.Property = 10;
}

IF에 따라 다르게 행동합니다 MySomething a struct 또는 a class. 나에게 이것은 매력적이지만 가장 설득력있는 이유는 아닙니다. 당신이 보면 DDD'에스 가치 객체, 스트러크가 어떻게 처리되어야하는지에 대한 연결을 볼 수 있습니다. DDD의 값 객체는 .NET (따라서 구조물)의 값 유형으로 가장 잘 표현 될 수 있습니다. 정체성이 없기 때문에 변경할 수 없습니다.

주소와 같은 측면에서 이것을 생각하십시오. 주소를 "변경"할 수 있지만 주소 자체는 변경되지 않았습니다. 실제로, 당신은 당신에게 새로운 주소가 할당되어 있습니다. 개념적으로, 이것은 당신이 실제로 만약 당신이 실제로 작동하기 때문에 변경 당신의 주소, 당신의 룸메이트도 움직여야 할 것입니다.

당신은 장단점을 요청했습니다 ~ 아니다 가이드 라인에 따라 스트러크는 불변이어야합니다.

단점 : 단점은 기존 답변으로 잘 다루어 있으며 설명 된 대부분의 문제는 동일한 원인으로 인한 것입니다. Structs의 가치 의미론으로 인한 예기치 않은 행동.

장점 : 돌연변이 성 스트러크를 사용하는 주요 전문가는 될 수 있습니다 성능. 분명히이 조언은 최적화에 대한 일반적인 경고와 함께 제공됩니다. 코드의 일부를 확인하십시오. 필요합니다 최적화하고 변경 사항이 실제로 프로파일 링을 통해 코드의 성능을 최적화하는지 확인하십시오.

Mutable Structs를 사용하고 싶은시기에 대한 훌륭한 기사는 Rico Mariani 's를 참조하십시오. 가치 기반 프로그래밍에 대한 성능 퀴즈 (또는 더 구체적으로, ).

구조물은 일반적으로 어떤 종류의 단일 통일성을 나타냅니다. 따라서 값의 속성 중 하나를 변경하는 것은 의미가 없습니다. 어떻게 든 다른 값을 원한다면 완전히 새로운 값을 만드는 것이 더 합리적입니다.

불변의 구조를 사용할 때 의미론이 더 간단 해지 며 다음과 같은 함정을 피합니다.

// a struct
struct Interval {
   int From { get; set; }
   int To { get; set; }
}

// create a list of structs
List<Interval> intervals = new List<Interval>();

// add a struct to the list
intervals.Add(new Interval());

// try to set the values of the struct
intervals[0].From = 10;
intervals[0].To = 20;

결과적으로 목록의 구조물이 전혀 변경되지 않았습니다. 표현식 간격 [0]은 목록에서 구조물의 값을 복사 한 다음 임시 값의 속성을 변경하지만 값은 목록에 다시 넣지 않습니다.

편집 : 배열 대신 목록을 사용하도록 예제를 변경했습니다.

주위의 스트러크를 복사 할 때는 내용을 복사하므로 복사 된 버전을 수정하면 "원본"이 업데이트되지 않습니다.

구조물을 복사하는 함정에 빠지고 (메서드에 전달하여) 사본을 수정하는 것을 알고 있으므로 오류의 소스입니다.

방금 나에게 일어났다 다시 지난주, 버그를 검색하는 데 한 시간을 보냈습니다.

불변의 스트러크를 유지하는 것은 그것을 방지합니다 ...

그 외에는 "최적화"또는 "스택에 빠르게 할당하는 것을 원한다"는 것이 답으로 간주되지 않는다는 것이 처음에 스트러크를 사용해야 할 충분한 이유가 있는지 확인해야합니다. 마샬링 또는 레이아웃에 의존하는 것 - 알겠습니다.하지만 일반적으로 그 구조를 매우 오랫동안 유지해서는 안되며, 객체가 아닙니다.

당신이 불변을 만들어야하는 이유는 그들이 Valuetypes, 당신이 그들을 메소드로 전달할 때마다 복사됩니다.

예를 들어, 구조물을 반환하는 속성이 있다면, 그 구조물의 필드 값을 수정하면 getter가 복사 구조물에 대한 참조가 아니라 구조물의. 나는 이것을 코드에서 수행하는 것을 보았고, 종종 잡기가 어렵다.

불변성을 위해 구조를 설계하면 프로그래머가 이러한 실수를 피하도록 도와줍니다.

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