2013-02-19 5 views
1

좋습니다. 이것은 실제 요구 사항보다 더 많은 호기심입니다.struct가 구조화되는 것을 방지 할 수있는 방법이 있습니까? 아니면 복사 할 클래스를 가질 수 있습니까?

의 내가이 클래스가 있다고 가정 해 봅시다 :이 클래스는 클래스 외부 인스턴스화이 작동하지 않을

public sealed class Entity 
{ 
    int value; 

    Entity() 
    { 

    } 

    public static implicit operator Entity(int x) 
    { 
     return new Entity { value = x }; 
    } 
} 

. 하지만 여기서 Entity은 참조되고 값 유형처럼 복사되지 않습니다. 이 클래스는 너무 작아서 좋아하는 값 유형을 사용하기를 원합니다. 또한 Entity의 두 인스턴스를 e1 == e2과 비교하면 참조 평등을 부여 할 수 있습니다. (그래도 ==을 오버로드 할 수 있지만 더 많은 작업이 필요합니다.)

public struct Entity 
{ 
    int value; 

    public static implicit operator Entity(int x) 
    { 
     return new Entity { value = x }; 
    } 
} 

을하지만 지금은 사람이 쉽게 new Entity()을 수행 할 수 있습니다 그래서 그것을 구조체를 만들 것입니다.

내 질문이 나는 타입 (구조체/클래스) 있음을 가질 수있는 방법

1)

Entity e1 = 1; 
Entity e2 = e1; 
ReferenceEquals(e1, e2); // prints false, just like any value type 

2) 값을 가지고 있도록 값에 액세스 할 때마다 복사됩니다

01 : 어떤지를 비교했을 때 의미가

Entity e1 = 1; 
Entity e2 = 1; 
e1.Equals(e2); // prints true 

// this is easy though by overriding default equality. 

3) 형식의 범위 밖 인스턴스화되지

기본적으로 enum의 동작에 가깝습니다. 나는 그것을 배우지 않고 살 수 있습니다.

+0

"Equals"메서드 또는 "=="연산자를 재정의하여 원하는 비교를 수행하지 못한다는 의미입니까? –

+0

@DavidW 예, 가능합니다. 하지만 여전히 클래스, 또는 즉 내 요구 사항 1에 대한 값 형식 의미를 부여 wouldnt. – nawfal

답변

2

C# 컴파일러가 매개 변수없는 생성자가 아무것도 수행하지 않는다는 가정을 기반으로 코드를 컴파일하기 때문에 C#에서 구조체의 기본 생성자를 다시 정의하거나 숨길 수 없습니다. Why can't I define a default constructor for a struct in .NET?을 참조하십시오.

귀하의 옵션 중 하나를

  • 이 구조체에 대한 기본 값 (예를 들어, 귀하의 경우에는 INT 0으로 초기화됩니다) 어떤 의미를 가지고 있는지 확인하는 클래스를
  • 를 사용하다 -이 열거 할 것입니다 (열거 형은 0으로 초기화됨을 상기하십시오).

성능 문제가 있음을 확인할 때까지 클래스를 사용하는 것이 좋습니다.

-1

클래스의 모든 생성자 (정적 생성자 외) privateEntity으로 만드십시오. protected도 작동하지만 sealed 이후로는 의미가 없습니다.

+0

당신은 내 질문을받지 못했다 것 같습니다. private 생성자를 만들면 인스턴스화 할 수 없지만 내 요구 사항 1을 충족할까요? 아니 .. – nawfal

+0

그냥 'Equals'를 오버라이드하지 않는 이유는 무엇입니까? –

+0

가능 합니다만, 참조 유형입니다. 그렇지 않으면 복사 될 값 유형이 아닙니다. 나는 내 질문을 편집 할 것이다. – nawfal

1

유형은 해당 유형의 저장 영역 위치에서 발생할 수있는 일에 대해 말하지 않습니다. 모든 유형의 저장 위치는 해당 유형의 다른 위치의 내용으로 내용이 덮어 쓰여질 수 있습니다. 유형 자체에 문제가있는 경우는 없습니다. 참조 유형의 저장 위치는 클래스 참조를 보유합니다. 존재하게되면 null 참조가됩니다.참조 유형의 저장 위치가 null 참조가 아닌 다른 것을 보유 할 수있는 유일한 방법은 해당 유형의 인스턴스가 생성되고 완전 신뢰 코드 및 반영과 관련된 일부 시나리오 외부 인 경우 참조 유형이 그것이 일어날 수있는 상황.

대조적으로 값 유형이 인 저장 위치는 해당 유형의 인스턴스입니다. 따라서 구조가 어떻게 생겨나는지 제어 할 수있는 방법이 없습니다. 제한된 범위 내에서 구조가 제어 할 수있는 것은 필드에 포함될 수있는 값입니다. 제한된 신뢰 시나리오에서 private struct 필드는 구조체의 코드가 struct의 일부 인스턴스에 해당 값을 쓰는 경우에만 기본값이 아닌 값을 취할 수 있습니다 (값이 struct의 인스턴스에 쓰여지거나 제한된 신뢰 코드 해당 인스턴스에 액세스하면 다중 스레드 겹침 읽기 및 쓰기를 사용하여 조합 (구조체 자체가 결코 자체 생성하지 않는 필드 값) 구조체를 생성 할 수 있습니다.

클래스 유형의 단일 개인 필드가있는 구조체를 만드는 것이 좋습니다. 코드가 default(Entity)을 생성하는 것을 막을 수는 없지만 코드에서 유용하게 사용할 수있는 코드를 허용해야한다는 의미는 아닙니다. 그 Equals 메서드는 다른 기본 인스턴스와 비교할 때 true을 반환하고, 다른 인스턴스와 비교할 경우 false을 반환 할 수 있어야하며 GetHashCode은 모든 기본 인스턴스에 대해 동일한 값을 반환해야하지만 다른 메서드는 예외를 throw 할 수 있습니다.

+0

클래스 유형의 개인용 백업 필드가있는 경우 어떤 이점이 있습니까? 구조체는 여전히 인스턴스화 가능합니다. 슬프게도 저의 원래 접근법 (저스틴의 답)과 함께 갈 것입니다. – nawfal

+0

@nawfal : 구조체에 클래스를 래핑하면 클래스 자체가 노출하는 것과 다른 메서드를 노출 할 수 있으며 기본 인스턴스의 동작을 제어 할 수도 있습니다. 누구나 어떤 유형의 변수 (클래스 또는 구조체)를 생성하고 해당 변수를 전달하는 메소드를 호출 할 수 있습니다. 클래스 형의 경우, 디폴트 값의 변수는'null'와 동일 해져 모든 메소드를 호출하려고하면 (자)'NullReferenceException'가 슬로우됩니다. 구조체를 사용하면 기본 인스턴스에서 어떤 효과 메서드가 있어야 하는지를 결정할 수 있습니다. – supercat