전달 - c# 생성자




모든 기본 매개 변수가있는 struct 생성자 호출 (4)

나는 오늘 데이터를 struct 를 만들 때이 문제에 부딪혔다. 다음은 그 예입니다.

public struct ExampleStruct
{
    public int Value { get; private set; }

    public ExampleStruct(int value = 1)
        : this()
    {
        Value = value;
    }
}

멋지고 멋쟁이 같다. 문제는 값을 지정하지 않고이 생성자를 사용하려고 시도하고 매개 변수에 기본값 1을 사용하려고 할 때입니다.

private static void Main(string[] args)
{
    ExampleStruct example1 = new ExampleStruct();

    Console.WriteLine(example1.Value);
}

이 코드는 0 을 출력하고 1 은 출력하지 않습니다. 그 이유는 모든 구조체에 매개 변수가없는 public 생성자가 있기 때문입니다. 예를 들어, new ExampleStruct() 가 실제로 ExampleStruct() 호출하지만 ExampleStruct(int value = 1) 호출하지 않는 곳에서 Main this() 내 명시 적 생성자를 호출하는 것과 같습니다. 이 작업을 수행하기 때문에 int 의 기본값 인 0을 Value 합니다.

설상가상으로 실제 코드는 int value = 1 매개 변수가 생성자 내에서 유효한 범위 내에 있는지 확인합니다. 위의 ExampleStruct(int value = 1) 생성자에 다음을 추가합니다.

if(value < 1 || value > 3)
{
    throw new ArgumentException("Value is out of range");
}

그래서, 지금 당장은 기본 생성자가 실제로 필요한 컨텍스트에서 유효하지 않은 객체를 생성했습니다. 누구든지 내가 어떻게 할 수 있는지 알고있다.

  • A. ExampleStruct(int value = 1) 생성자를 호출합니다.
  • B. ExampleStruct() 생성자에 대한 기본값이 채워지는 방법을 수정합니다.
  • C. 다른 제안 / 옵션.

또한, 저는 Value 프로퍼티 대신에 다음과 같은 필드를 사용할 수 있다는 것을 알고 있습니다 :

public readonly int Value;

하지만 제 철학은 conststatic 이 아닌 이상 필드를 사적으로 사용하는 것입니다.

마지막으로, class 대신 struct 를 사용하는 이유는 단순히 변경 불가능한 데이터를 보유하기위한 객체이고, 생성 될 때 완전히 채워 져야하며 매개 변수로 전달 될 때 수 있어야한다는 것입니다. null ( struct 의해 value에 의해 전달되기 때문에)은 struct가 설계 한 것이다.


나는 그것이 좋은 구조라고 생각하지 않는다.

default(ExampleStruct)

즉 모든 인스턴스 필드가 0 / false / null 인 값은 구조체의 유효한 값이 아닙니다 . 그리고 아시다시피, 당신이 말할 때

new ExampleStruct()

이는 default(ExampleStruct) 와 동일하며 모든 필드 (자동 속성의 생성 된 필드 포함)가 0 인 구조체의 값을 제공합니다.

어쩌면 당신은 이것을 할 수 있습니다 :

public struct ExampleStruct
{
  readonly int valueMinusOne;

  public int Value { get { return valueMinusOne + 1; } }

  public ExampleStruct(int value)
  {
    valueMinusOne = value - 1;
  }
}

왜 당신은 public ExampleStruct(int value = 1) : this() ?

그것은 public ExampleStruct(int value = 1) 이 아니어야합니다 public ExampleStruct(int value = 1) ? 나는 :this() 가 인자없는 생성자를 생성하고 있다고 생각한다.


사실, MSDN에는 struct 에 대한 좋은 지침이 있습니다.

유형의 인스턴스가 작고 일반적으로 수명이 짧거나 일반적으로 다른 객체에 포함되는 경우 클래스 대신 구조를 정의하는 것이 좋습니다.

유형에 다음 특성이 모두있는 경우가 아니면 구조를 정의하지 마십시오.

논리적으로 단일 값 (정수, double 등)과 비슷한 단일 값을 나타냅니다.

인스턴스 크기가 16 바이트보다 작습니다.

불변입니다.

자주 박스에 넣지 않아도됩니다.

struct고려할 때 고려해야 할 사항 이며 "항상 구조체 여야합니다 ."라는 것을주의하십시오. 왜냐하면 struct 를 사용하기위한 선택은 성능과 사용상의 의미 (양수 및 음수)를 가질 수 있기 때문에 신중하게 선택해야하기 때문입니다.

특히 16 바이트를 초과하는 경우 struct 를 권장하지 않습니다 (복사 비용은 참조 복사보다 비쌉니다).

자, 경우, 기본 상태에서 당신을 위해 struct 를 생성하는 공장을 만들거나 첫 번째 사용에 초기화로 속일 자신의 속성에 trick 를 수행하는 이외의 다른 일을 정말로 좋은 방법이 없습니다.

structnew X() == default(X) 즉 새로 생성 된 struct 가 해당 struct 모든 필드에 대한 기본값을 포함하도록 작동해야합니다. C #에서는 struct 대해 매개 변수없는 생성자를 정의 할 수 없으므로이 인수는 매우 분명합니다. 모든 인수가 경고없이 기본값으로 설정 될 수 있다는 점이 궁금합니다.

따라서, 나는 실제로 당신이 class 를 고수하고 그것을 불변으로 만들고 전달 된 메소드에서 null 을 체크 할 것을 제안한다.

public class ExampleClass
{
    // have property expose the "default" if not yet set
    public int Value { get; private set; }

    // remove default, doesn't work
    public ExampleStruct(int value)
    {
        Value = value;
    }
}

그러나 , 당신이 절대적으로 다른 이유에 대한 struct있어야합니다 -하지만 복사 - 캐스트 등 struct 의 비용을 고려하시기 바랍니다 - 당신이 할 수있는 :

public struct ExampleStruct
{
    private int? _value;

    // have property expose the "default" if not yet set
    public int Value
    {
        get { return _value ?? 1; }
    }

    // remove default, doesn't work
    public ExampleStruct(int value)
        : this()
    {
        _value = value;
    }
}

기본적으로 Nullable<int>null (즉, HasValue == false )이되므로 true이면 아직 설정하지 않았고 null 합치기 연산자를 사용하여 기본값을 반환 할 수 있습니다. 1 대신에. 우리 생성자에서 그것을 설정했다면, 그것은 null이 아니며 대신 그 값을 취할 것입니다 ...


new T() 가 "모든 0"기본값 이외의 다른 값으로 설정된 필드를 가지도록 일부 언어 (Cil은 아무것도 작성하지 않은 경우)가 struct 생성자를 정의 할 수 있지만 C # 및 vb.net (및 대부분의 다른 언어)에서는 배열 요소와 클래스 필드 같은 것들은 항상 default(T) 으로 초기화되어야하고, new T() 와 일치하지 않는 것으로 초기화되어야하기 때문에 구조가 혼란스럽고 구조는 new T()default(T) 이외의 것을 의미합니다.

필자는 매개 변수가있는 생성자에서 기본 매개 변수를 jinx하려고 시도하는 대신 원하는 기본 값을 반환하는 정적 struct 속성을 정의하고 new ExampleStruct() 가 발생할 때마다 new ExampleStruct() 바꿀 것을 제안합니다 ExampleStruct.NiceDefault; .

2015 년 부록

C #과 VB.NET은 매개 변수없는 struct 생성자를 정의하는 것에 대한 금지를 완화 할 수 있습니다. 이로 인해 Dim s = New StructType() 과 같은 명령문에서 s 지정된 값과 다른 값을 StructType 유형의 새 배열 항목에 StructType 있습니다. C #의 default(StructType) 유사한 것이 존재한다면 더 적절한 장소에서 종종 new StructType 이 사용된다는 점을 감안할 때, 나는 변화에 매우 열중하지 않습니다. VB.NET은 Dim s As StructType = Nothing 허용 할 것이지만, 다소 Dim s As StructType = Nothing 보입니다.







default-constructor