programing

상수 배열 선언

kakaobank 2023. 5. 2. 22:54
반응형

상수 배열 선언

다음과 같은 것을 쓰는 것이 가능합니까?

public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

은 그것을 만, 합니다야셔신하로 해야 합니다.readonlyconst:

public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

는 그는이 때문입니다.const컴파일 시 값이 알려진 필드에만 적용할 수 있습니다.당신이 보여준 배열 이니셜라이저는 C#의 상수식이 아니므로 컴파일러 오류가 발생합니다.

선언하기readonly값은 런타임까지 초기화되지 않으므로 이 문제를 해결합니다(어레이가 처음 사용되기 전에 초기화되었음이 보장됨).

궁극적으로 달성하고자 하는 목표에 따라 열거형을 선언하는 것도 고려할 수 있습니다.

public enum Titles { German, Spanish, Corrects, Wrongs };

배열은 개체이며 런타임에만 생성할 수 있고 구성 요소는 컴파일 시 확인되므로 'const' 배열을 만들 수 없습니다.

대신 어레이를 "읽기 전용"으로 선언할 수 있습니다.이는 런타임에 값을 설정할 수 있다는 점을 제외하고는 const와 동일한 효과를 갖습니다.한 번만 설정할 수 있으며 읽기 전용(즉, const) 값 이후에 설정됩니다.

어레이를 다음과 같이 선언할 수 있습니다.readonly▁of▁element요▁change▁but의 요소를 변경할 수 있다는 것을 명심하세요.readonlyvmdk

public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";

Cody가 제안한 대로 열거형 또는 IList를 사용해 보십시오.

public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();

이것이 유일한 정답입니다.현재 이 작업을 수행할 수 없습니다.

다른 모든 답변은 상수와 비슷하지만 동일하지 않은 정적 읽기 전용 변수를 사용할 것을 제안합니다.상수가 어셈블리에 하드 코딩됩니다.정적 읽기 전용 변수는 개체가 초기화될 때 한 번 설정할 수 있습니다.

이것들은 때때로 서로 교환할 수 있지만 항상 그렇지는 않습니다.

편집: 질문을 한 사람이 배열에 대해 약간 모호하게 생각했기 때문에, 저는 이것을 집어넣어야겠다고 생각했습니다.어레이를 선언하면 어레이가 포함된 메모리 세그먼트에 대한 포인터가 됩니다.읽기 또는 쓰기 가능 여부를 제어하는 복잡한 논리가 없는 단순한 주소입니다.그것은 당신에게 포인터를 제공하고, 당신은 그것으로 당신이 원하는 것을 할 수 있습니다.

이것은 불변의 배열을 만드는 것이 조금 까다로운 이유의 일부입니다.배열을 래핑하고 복사본을 반환하여 읽기만 허용하는 클래스를 작성할 수 있습니다. 하지만 이제는 단순히 배열이 아니라 배열을 래핑하는 개체입니다.

일부 사람들은 정적 또는 읽기 전용을 사용하여 상수 배열을 만들 수 있는 경우 표시되는 동작을 시뮬레이션할 것을 제안했습니다.이것들은 일상적인 독자들에게 분명하지 않을 수 있는 몇 가지 부작용을 가지고 있습니다.또한 배열을 읽기 전용으로 표시하는 경우에는 배열 자체가 아니라 배열에 대한 포인터를 표시하는 것입니다.원하는 만큼 배열 내용을 변경할 수 있습니다.

public class Demo
{
    private readonly int[] _foo = new int[] {0,1,2,3};
    
    public void ChangeArray()
    {
        _foo[1] = 42; // works
        _foo = new int[] { 0, 1, 2, 3, 5 }; // won't even compile
    }
}

상수 배열을 제대로 얻으려면 배열에서 읽을 수 있도록 C# 및 MSIL 기본 코드에 대한 업데이트가 있어야 하지만 쓰기는 허용되지 않습니다.이 페이지의 다른 제안은 이 문제를 해결하기 위한 다양한 창의적인 방법입니다.

C# 6부터는 다음과 같이 쓸 수 있습니다.

public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };

참고 항목:C# : 새로운 C# 6.0 (구체적으로 "표현물 본문 기능 및 속성" 장)

이렇게 하면 읽기 전용 정적 속성이 되지만 반환되는 배열의 내용을 변경할 수는 있지만 속성을 다시 호출하면 원래의 변경되지 않은 배열이 다시 표시됩니다.

설명을 위해 이 코드는 다음과 같습니다.

public static string[] Titles
{
    get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}

이 접근 방식에는 단점이 있습니다. 새 어레이는 실제로 각 참조에서 인스턴스화되므로 매우 큰 어레이를 사용하는 경우 이 솔루션이 가장 효율적이지 않을 수 있습니다.그러나 동일한 배열을 다시 사용하는 경우(예를 들어 개인 속성에 넣어) 배열의 내용을 변경할 수 있습니다.

불변 배열(또는 목록)을 사용하려면 다음을 사용할 수도 있습니다.

public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };

그러나 문자열[]로 다시 캐스트하고 다음과 같이 내용을 변경할 수 있으므로 변경 위험이 있습니다.

((string[]) Titles)[1] = "French";

완전성을 위해 이제 우리는 또한 자유롭게 사용할 수 있습니다.이것은 정말 불변의 것이어야 합니다.

public readonly static ImmutableArray<string> Titles =
    ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });

요사구가 합니다.System.Collections.ImmutableNuGet 참조.

.NET Framework v4.5+ 솔루션tdbecket의 답변을 개선합니다.

using System.Collections.ObjectModel;

// ...

public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
  new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);

참고: 컬렉션이 개념적으로 일정하다는 점을 고려할 때, 이를 이해하는 것이 타당할 수 있습니다.static클래스 레벨에서 선언합니다.

위 내용:

  • 배열을 사용하여 속성 암시적 백업 필드를 한 번 초기화합니다.

    • :{ get; }즉, 속성 게터만 선언하는 것은 속성 자체를 암묵적으로 읽기 전용으로 만드는 것입니다(결합할 필요가 없습니다).readonly와 함께{ get; }실제로는 구문 오류입니다.

    • 또는 다음을 생략할 수 있습니다.{ get; } 가추를 합니다.readonly질문과 같이 속성 대신 필드를 만드는 것이지만 공용 데이터 구성원을 필드가 아닌 속성으로 노출하는 것은 좋은 습관입니다.

  • 다음과 같은 측면에서 진정하고 강력한 읽기 전용(개념적으로 일정하게 생성된 후)인 어레이유사한 구조(인덱스 액세스 허용)를 만듭니다.

    • 요소를 제거하거나 추가하거나 변수에 새 컬렉션을 할당하여 컬렉션 전체 수정할 수 없습니다.
    • 개별 요소의 수정을 방지합니다.
      (간접적인 수정도 불가능합니다. 솔루션과 달리 젭슨의 유용한 답변에 나와 있듯이 주조물을 사용하여 요소에 대한 쓰기 액세스 권한을 얻을있습니다.
      인터페이스에도 동일한 취약성이 적용되며, 이 취약성은 클래스와 이름이 유사함에도 불구하고 ReadOnlyCollection인덱스된 액세스도 지원하지 않으므로 어레이와 같은 액세스를 제공하기에는 근본적으로 적합하지 않습니다.)

IRadOnlyList 인터페이스 뒤에 배열을 선언하면 런타임에 선언된 상수 값을 가진 상수 배열이 표시됩니다.

public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };

에서 사용할 수 있습니다.NET 4.5 이상.

배열을 나타내는 상수 문자열을 정의한 다음 필요할 때 문자열을 배열로 분할하는 등 다른 접근 방식을 사용할 수 있습니다.

const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');

이 접근 방식은 구성에 저장하고 필요할 때 배열로 변환할 수 있는 상수를 제공합니다.

저는 당신이 읽기만 할 수 있다고 믿습니다.

나는 나의 필요를 위해 정의합니다.static 대신 , impossible, arrayconst효과가 있습니다.public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

원하는 작업을 수행할 수 있는 방법은 다음과 같습니다.

using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;

public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}

읽기 전용 배열을 수행하는 것과 매우 유사합니다.

어레이는 런타임에만 평가할 수 있는 것 중 하나일 것입니다.컴파일 시 상수를 평가해야 합니다."const" 대신 "read only"를 사용해 보십시오.

최상의 대안:

public static readonly byte[] ZeroHash = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

다른 사용자에게 도움이 될 경우 빠른 해결 방법.나는 필요했습니다.string[](일부 이론에서 테스트 사례에 대한 인라인 데이터 전달) 속성에 대한 인수가 됩니다. readonly여기선 도움이 안 됩니다.하지만, 저는 결국 다음과 같이 했습니다.

const string foo = "a|b|c";

[InlineData(foo)]
public void Test(string fooString)
{
    var foo = fooString.Split("|"); // foo == {"a","b","c"}
    ...
}

또는 읽기 전용 어레이에서 수정할 수 있는 요소 문제를 해결하기 위해 정적 속성을 대신 사용할 수 있습니다.개별 요소는 계속 변경할 수 있지만 이러한 변경은 어레이의 로컬 복사본에서만 수행됩니다.

public static string[] Titles 
{
    get
    {
        return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
    }
}

물론 매번 새 문자열 배열이 만들어지기 때문에 특별히 효율적이지는 않습니다.

언급URL : https://stackoverflow.com/questions/5142349/declare-a-const-array

반응형