답변:
예, 그러나 readonly
대신 다음과 const
같이 선언해야합니다 .
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
그 이유는 const
컴파일 타임에 값이 알려진 필드에만 적용 할 수 있기 때문입니다 . 표시 한 배열 이니셜 라이저는 C #에서 상수 표현식이 아니므로 컴파일러 오류가 발생합니다.
readonly
이 값을 선언하면 런타임까지 값이 초기화되지 않기 때문에이 문제가 해결됩니다 (배열을 처음 사용하기 전에 초기화 된 것이 보장되지만).
궁극적으로 달성하고자하는 것이 무엇인지에 따라 열거 형 선언을 고려할 수도 있습니다.
public enum Titles { German, Spanish, Corrects, Wrongs };
readonly static
요청 된 의미의 유사성을 가지고.
static
그것이 작동하게 할 필요는 없지만 Titles
인스턴스를 가지지 않고 참조 할 가능성을 추가 하지만 다른 인스턴스의 값을 변경할 가능성을 제거하십시오 (예 : 해당 readonly
필드의 값을 변경하는 것에 따라 매개 변수가있는 생성자를 가질 수 있음 ).
배열을 다음과 같이 선언 할 수 있습니다 readonly
있지만 readonly
array 요소를 변경할 수 있습니다 .
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();
const
아닙니다 readonly
...
배열은 객체이고 런타임에만 만들 수 있고 const 엔터티는 컴파일 타임에 확인되므로 'const'배열을 만들 수 없습니다.
대신 배열을 "읽기 전용"으로 선언하면됩니다. 런타임에 값을 설정할 수 있다는 점을 제외하면 const와 동일한 효과가 있습니다. 한 번만 설정할 수 있으며 이후 읽기 전용 (즉, const) 값입니다.
const int[] a = null;
는별로 유용하지는 않지만 실제로 배열 상수의 인스턴스입니다.
C # 6부터 다음과 같이 작성할 수 있습니다.
public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };
참조 : C # .NET을 : 새로운 및 향상된 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";
Titles[0]
예를 들어 할당 시도가 자동으로 무시되는 경우 컴파일 오류가 발생하지 않습니다 . 매번 배열을 다시 생성하는 비효율 성과 결합 하여이 접근법이 가치가 있는지 궁금합니다. 대조적으로, 두 번째 접근 방식은 효율적이므로 불변성을 없애기 위해 길을 떠나야합니다.
.NET 프레임 워크 V4.5의 + 솔루션 에 향상 tdbeckett의 대답 :
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
참고 : 컬렉션이 개념적으로 일정 static
하면 클래스 수준 에서 컬렉션 을 선언하는 것이 좋습니다.
위 :
배열을 사용 하여 속성의 암시 적 백업 필드를 한 번 초기화합니다 .
하는 것으로 { get; }
- 즉, 단지 속성 선언 게터을 - 암시 적으로 읽기 전용 속성 자체를 만드는 것입니다 (결합하는 시도 readonly
와 함께하는 것은 { get; }
실제로 구문 오류입니다).
또는 질문에서와 같이 속성 대신 필드 를 생성하기 위해 { get; }
및 추가 readonly
를 생략 할 수 있지만 공개 데이터 멤버를 필드가 아닌 속성으로 노출 하는 것이 좋은 습관입니다.
다음 과 관련하여 진정으로 강력하게 읽기 전용 (개념적으로 일정하고 일단 생성 된) 인 배열 과 유사한 구조 ( 인덱스 액세스 허용 )를 만듭니다 .
IReadOnlyList<T>
용액 캐스트 요소에 대한 쓰기 액세스를 얻기 위해 사용될 수있다 같이 mjepsen의 도움 않음 .
동일한 취약점이 적용 인터페이스 이름 유사성에도 불구하고, 이는 로 클래스 , 심지어 지원하지 않는 인덱스 액세스를 액세스 어레이 형상 제공하는 것이 근본적으로 적합하지 않다.)(string[])
IReadOnlyCollection<T>
ReadOnlyCollection
IReadOnlyCollection
인덱스 액세스를 지원하지 않으므로 여기서 사용할 수 없습니다. 또한 IReadOnlyList
(인덱스 액세스 권한이있는) 처럼로 다시 캐스팅하여 요소를 조작하기 쉽습니다 string[]
. 즉, ReadOnlyCollection
(문자열 배열을 캐스트 할 수없는) 가장 강력한 솔루션입니다. 게터를 사용하지 않는 것이 옵션이지만 ( 공개 데이터 를 참고하여 답변을 업데이트했습니다) 공개 데이터를 사용하면 속성을 유지하는 것이 좋습니다.
내 필요 static
에 따라 불가능 대신 배열을 정의 const
하고 작동합니다.
public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
const
OP 예제에서 간단히 제거해 도 작동하지만 Titles
인스턴스 또는 모든 값 을 변경할 수 있습니다 . 이 답변의 요점은 무엇입니까?
readonly
다른 접근법을 취할 수 있습니다 : 배열을 나타내는 상수 문자열을 정의한 다음 필요할 때 문자열을 배열로 분할하십시오.
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
이 접근 방식은 상수를 제공하여 구성에 저장하고 필요할 때 배열로 변환 할 수 있습니다.
완벽을 기하기 위해 이제 우리는 또한 ImmutableArrays를 사용할 수 있습니다. 이것은 정말로 불변이어야합니다 :
public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
System.Collections.Immutable NuGet 참조 필요
https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx
이것은 원하는 것을 수행하는 방법입니다.
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
읽기 전용 배열을 수행하는 것과 매우 유사합니다.
public static readonly ReadOnlyCollection<String> Titles = new List<String> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
; 어쨌든 ReadOnlyCollection으로 만들면 모든 검색에서 목록을 다시 만들 필요가 없습니다.