언제 클래스 대신 구조체를 사용해야합니까?
MSDN은 가벼운 객체가 필요할 때 구조체를 사용해야한다고 말합니다. 클래스보다 구조체가 선호되는 다른 시나리오가 있습니까?
어떤 사람들은 그것을 잊었을 수도 있습니다.
- 구조체 는 메소드를 가질 수 있습니다.
- 구조체 는 상속 될 수 없습니다.
구조체와 클래스의 기술적 차이점을 이해합니다 . 구조체를 사용할 때 기분이 좋지 않습니다 .
MSDN에는 다음과 같은 대답이 있습니다. 클래스와 구조 간 선택 .
기본적으로이 페이지는 4 가지 항목 점검 목록을 제공하며 유형이 모든 기준을 충족하지 않는 한 클래스를 사용하도록 지시합니다.
유형에 다음 특성이 모두없는 한 구조를 정의하지 마십시오.
- 기본 유형 (정수, 이중 등)과 유사한 단일 값을 논리적으로 나타냅니다.
- 인스턴스 크기가 16 바이트보다 작습니다.
- 불변입니다.
- 자주 박스에 넣을 필요는 없습니다.
이전 답변을 읽지 않은 것에 놀랐습니다. 가장 중요한 측면을 고려합니다.
나는 정체성이없는 유형을 원할 때 구조체를 사용합니다. 예를 들어 3D 점 :
public struct ThreeDimensionalPoint
{
public readonly int X, Y, Z;
public ThreeDimensionalPoint(int x, int y, int z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
public override string ToString()
{
return "(X=" + this.X + ", Y=" + this.Y + ", Z=" + this.Z + ")";
}
public override int GetHashCode()
{
return (this.X + 2) ^ (this.Y + 2) ^ (this.Z + 2);
}
public override bool Equals(object obj)
{
if (!(obj is ThreeDimensionalPoint))
return false;
ThreeDimensionalPoint other = (ThreeDimensionalPoint)obj;
return this == other;
}
public static bool operator ==(ThreeDimensionalPoint p1, ThreeDimensionalPoint p2)
{
return p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z;
}
public static bool operator !=(ThreeDimensionalPoint p1, ThreeDimensionalPoint p2)
{
return !(p1 == p2);
}
}
이 구조체의 인스턴스가 두 개인 경우 메모리의 단일 데이터인지 두 개인 지 상관하지 않습니다. 당신은 그들이 보유한 가치에 관심이 있습니다.
Bill Wagner는 그의 책 "effective c #"( http://www.amazon.com/Effective-Specific-Ways-Improve-Your/dp/0321245660 ) 에서 이에 관한 장을 가지고 있습니다. 그는 다음 원리를 사용하여 결론을 맺습니다.
- 유형 데이터 스토리지의 주요 책임은 무엇입니까?
- 공용 인터페이스는 데이터 멤버에 액세스하거나 수정하는 속성으로 만 정의됩니까?
- 타입에 서브 클래스가 절대 없을까요?
- 타입이 다형성으로 취급되지 않습니까?
네 가지 질문 모두에 '예'라고 대답하면 구조체를 사용하십시오. 그렇지 않으면 클래스를 사용하십시오.
참조 유형 대신 값 유형 시맨틱을 원할 때 구조체를 사용하십시오. Structs는 값별로 복사되므로주의하십시오!
예를 들어 이전 질문을 참조하십시오.
다음과 같은 경우 구조체를 사용합니다.
객체는 읽기 전용이어야합니다 (복사 될 구조체를 전달 / 할당 할 때마다). 읽기 전용 객체는 대부분의 경우 잠금이 필요하지 않으므로 멀티 스레드 처리에 유용합니다.
물체는 작고 수명이 짧습니다. 이러한 경우 관리 힙에 배치하는 것보다 훨씬 효율적인 스택에 오브젝트가 할당 될 가능성이 높습니다. 객체가 할당 한 메모리가 더 이상 범위를 벗어나면 해제됩니다. 즉, 가비지 콜렉터의 작업이 적고 메모리가 더 효율적으로 사용됩니다.
다음과 같은 경우 수업을 이용하십시오 :
- 정체성이 중요합니다. 값으로 메소드에 전달 될 때 구조가 암시 적으로 복사됩니다.
- 메모리 공간이 큽니다.
- 필드에는 이니셜 라이저가 필요합니다.
- 기본 클래스에서 상속해야합니다.
- 다형성 동작이 필요합니다.
다음과 같은 경우 구조를 사용하십시오.
- 기본 유형 (int, long, byte 등)처럼 작동합니다.
- 메모리 사용량이 적어야합니다.
- 값으로 구조를 전달해야하는 P / Invoke 메소드를 호출하고 있습니다.
- 가비지 수집이 응용 프로그램 성능에 미치는 영향을 줄여야합니다.
- 해당 필드는 기본값으로 만 초기화해야합니다. 이 값은 숫자 유형의 경우 0, 부울 유형의 경우 false, 참조 유형의 경우 null입니다.
- C # 6.0에서 구조체에는 구조체의 필드를 기본값이 아닌 값으로 초기화하는 데 사용할 수있는 기본 생성자가있을 수 있습니다.
- 기본 클래스 (모든 구조체가 상속하는 ValueType 이외)에서 상속 할 필요는 없습니다.
- 다형성 동작이 필요하지 않습니다.
메소드 호출에서 물건을 다시 전달하기 위해 몇 가지 값을 그룹화하고 싶을 때 항상 구조체를 사용했지만 그 값을 읽은 후에는 아무것도 사용할 필요가 없습니다. 물건을 깨끗하게 유지하는 방법으로. 나는 구조체의 사물을 "쓰레기"라고 생각하고 수업의 사물을 더 유용하고 "기능적"으로 보는 경향이있다
엔터티를 변경할 수없는 경우 구조체 또는 클래스를 사용할지 여부에 대한 문제는 일반적으로 의미론보다는 성능의 문제입니다. 32/64 비트 시스템에서 클래스 참조는 클래스의 정보량에 관계없이 4/8 바이트를 저장해야합니다. 클래스 참조를 복사하려면 4/8 바이트를 복사해야합니다. 다른 한편으로, 모든 별개의클래스 인스턴스는 보유하고있는 정보와 이에 대한 참조의 메모리 비용 외에 8/16 바이트의 오버 헤드를 갖습니다. 각각 4 개의 32 비트 정수를 보유하는 500 개의 엔티티 배열을 원한다고 가정하십시오. 엔티티가 구조 유형 인 경우 배열은 500 개의 엔티티가 모두 동일하거나 모두 다르거 나 사이에 관계없이 8,000 바이트를 필요로합니다. 엔터티가 클래스 유형 인 경우 500 개의 참조 배열에는 4,000 바이트가 필요합니다. 이러한 참조가 모두 다른 객체를 가리키는 경우 객체는 각각 추가 24 바이트 (500 개당 12,000 바이트), 총 16,000 바이트 (구조 유형의 스토리지 비용의 두 배)가 필요합니다. 다른 한편으로, 코드는 하나의 객체 인스턴스를 생성 한 다음 500 개의 모든 배열 슬롯에 대한 참조를 복사 했으므로 총 비용은 해당 인스턴스의 경우 24 바이트, 배열의 경우 4,000 (총 4, 024 바이트 주요 절감 효과. 마지막 상황뿐만 아니라 거의 상황이 해결되지 않지만 경우에 따라 공유를 가치있게 만들기 위해 충분한 배열 슬롯에 일부 참조를 복사 할 수 있습니다.
엔티티가 변경 가능 해야하는 경우 클래스 또는 구조체를 사용할지 여부에 대한 질문이 더 쉽습니다. "Thing"은 x라는 정수 필드를 가진 구조체 또는 클래스이고 다음 코드를 수행한다고 가정합니다.
일 t1, t2; ... t2 = t1; t2.x = 5;
후자의 진술이 t1.x에 영향을 미치 길 원합니까?
Thing이 클래스 유형 인 경우 t1과 t2는 동일하므로 t1.x와 t2.x도 동일합니다. 따라서 두 번째 문장은 t1.x에 영향을 미칩니다. Thing이 구조 유형 인 경우 t1과 t2는 서로 다른 인스턴스가되므로 t1.x와 t2.x는 서로 다른 정수를 나타냅니다. 따라서 두 번째 문장은 t1.x에 영향을 미치지 않습니다.
.net에는 구조체 돌연변이 처리에 약간의 단점이 있지만 가변 구조와 가변 클래스는 근본적으로 다른 동작을합니다. 값 유형 동작을 원하면 ( "t2 = t1"은 t1과 t2를 별개의 인스턴스로 남겨두고 t1에서 t2로 데이터를 복사 함을 의미 함) .net에서 값 유형을 처리 할 때 문제가 생길 수있는 경우 구조. 밸류 타입 시맨틱을 원하지만 .net의 쿼크로 인해 애플리케이션에서 밸류 타입 시맨틱이 깨질 경우 클래스를 사용하고 중얼 거린다.
또한 위의 우수한 답변 :
구조는 가치 유형입니다.
절대 Nothing 으로 설정할 수 없습니다 .
구조체 = Nothing을 설정하면 모든 값 유형이 기본값으로 설정됩니다.
실제로 동작이 필요하지 않지만 간단한 배열이나 사전보다 더 많은 구조가 필요합니다.
후속 조치 이것은 일반적으로 구조체에 대한 생각입니다. 나는 그들이 방법을 가질 수 있다는 것을 알고 있지만, 전반적인 정신 구분을 유지하는 것을 좋아합니다.
@Simon이 말했듯이 구조체는 "값 형식"의미를 제공하므로 내장 데이터 형식과 유사한 동작이 필요한 경우 구조체를 사용하십시오. 구조체는 복사본으로 전달되므로 크기가 약 16 바이트인지 확인하려고합니다.
흠 ...
구조체 대 클래스 사용에 대한 가비지 수집을 인수로 사용하지 않습니다. 관리되는 힙은 스택과 매우 유사하게 작동합니다. 개체를 만들면 힙의 맨 위에 놓이므로 스택에 할당하는 것만 큼 빠릅니다. 또한 개체의 수명이 짧고 GC주기에서 살아남지 못하면 GC가 여전히 액세스 가능한 메모리에서만 작동하므로 할당 해제가 무료입니다. (MSDN 검색, .NET 메모리 관리에 대한 일련의 기사가 있습니다. 발굴하기에는 너무 게으르다).
구조체를 사용하는 대부분의 경우, 나중에 참조 의미론을 갖는 것이 일을 조금 더 간단하게 만들었 음을 알게 되었기 때문에 그렇게하는 것에 대해 스스로를 쫓아 버립니다.
어쨌든 위에 게시 된 MSDN 기사의 4 가지 사항은 좋은 지침으로 보입니다.
Structs는 힙이 아닌 스택에 있으므로 스레드로부터 안전하므로 전송 객체 패턴을 구현할 때 사용해야합니다. 힙에서 객체를 휘발성으로 사용하지 않으려는 경우,이 경우 콜 스택을 사용하려고합니다. 이것은 내가 여기에 모든 답변에 놀란 구조체를 사용하는 기본 사례입니다.
가장 좋은 대답은 필요한 속성 모음, 클래스가 속성 및 동작 모음 인 경우 클래스를 사용하는 것입니다.
참고 URL : https://stackoverflow.com/questions/85553/when-should-i-use-a-struct-instead-of-a-class
'Programing' 카테고리의 다른 글
옵션이있는 명령 줄에서 .sql 파일을 내보내고 가져 오는 방법은 무엇입니까? (0) | 2020.03.17 |
---|---|
비동기 작업을 동 기적으로 대기하는 이유와 여기서 Wait ()가 프로그램을 정지시키는 이유 (0) | 2020.03.17 |
C ++ 코드는 C ++ 03 및 C ++ 11에서 모두 유효하지만 다른 작업을 수행 할 수 있습니까? (0) | 2020.03.17 |
Swift에서 배열을 섞는 방법은 무엇입니까? (0) | 2020.03.16 |
iTerm2 키보드 단축키-분할 분할 창 탐색 (0) | 2020.03.16 |