문제

어떻게 든 마크 a가 가능합니까? System.Array 불변. 공공 기관/개인 세트 뒤에 놓을 때 재 할당 및 재 할당이 필요하기 때문에 추가 할 수는 없지만 소비자는 여전히 원하는 첨자를 설정할 수 있습니다.

public class Immy
{
    public string[] { get; private set; }
}

나는 생각했다 readonly 키워드는 트릭을 수행 할 수 있지만 그런 운은 없습니다.

도움이 되었습니까?

해결책

ReadOnlyCollection<T> 아마도 당신이 찾고있는 것일 것입니다. 그것은 없습니다 Add() 방법.

다른 팁

그만큼 프레임 워크 설계 지침 배열 사본을 반환하는 것이 좋습니다. 그렇게하면 소비자는 배열에서 항목을 변경할 수 없습니다.

// bad code
// could still do Path.InvalidPathChars[0] = 'A';
public sealed class Path {
   public static readonly char[] InvalidPathChars = 
      { '\"', '<', '>', '|' };
}

이것들은 더 낫다 :

public static ReadOnlyCollection<char> GetInvalidPathChars(){
   return Array.AsReadOnly(InvalidPathChars);
}

public static char[] GetInvalidPathChars(){
   return (char[])InvalidPathChars.Clone();
}

그 예는 책에서 바로 있습니다.

참조하십시오 이제 불변의 컬렉션을 사용할 수 있습니다 기본 클래스 라이브러리 (현재 미리보기)에서.

Array.asreadonly 메소드를 사용하여 반환 할 수 있습니다.

모범 사례는 Ilist를 사용하는 것입니다u003CT> 이 정확한 이유 때문에 공개 API의 배열보다는 대신. 준비 적 멤버 변수가 생성자 외부에서 설정되는 것을 방지하지만 발견 한대로 사람들이 배열에 요소를 할당하는 것을 방해하지는 않습니다.

보다 어레이는 다소 유해하다고 생각합니다 자세한 내용은.

편집하다: 배열 만 읽을 수는 없지만 @shahkalpesh가 지적한대로 array.asreadonly ()를 통해 읽기 전용 ILIST 구현으로 변환 할 수 있습니다.

.NET은 가장 단순하고 전통적인 사용 사례를 제외한 모든 배열에서 멀어지는 경향이 있습니다. 다른 모든 것에 대해, 다양한 열거 가능한/수집 구현이 있습니다.

일련의 데이터를 불변으로 표시하려면 기존 배열에서 제공하는 기능을 넘어서고 있습니다. .NET은 동등한 기능을 제공하지만 기술적으로 배열 형태는 아닙니다. 어레이에서 불변의 컬렉션을 얻으려면 사용하십시오. Array.AsReadOnly<T>:

var mutable = new[]
{
    'a', 'A',
    'b', 'B',
    'c', 'C',
};

var immutable = Array.AsReadOnly(mutable);

immutable a ReadOnlyCollection<char> 사례. 보다 일반적인 사용 사례로서 ReadOnlyCollection<T> 모든 일반에서 IList<T> 구현.

var immutable = new ReadOnlyCollection<char>(new List<char>(mutable));

일반적인 구현이어야합니다. 평범한 늙음 IList 작동하지 않으면 기존 배열 에서이 방법을 사용할 수 없다는 의미입니다. IList. 이것은 사용 가능성을 밝히게합니다 Array.AsReadOnly<T> 일반적으로 기존 배열을 통해 접근 할 수없는 일반 구현에 대한 액세스를 얻는 빠른 수단으로.

ReadOnlyCollection<T> 불변의 배열에서 기대할 모든 기능에 액세스 할 수 있습니다.

// Note that .NET favors Count over Length; all but traditional arrays use Count:
for (var i = 0; i < immutable.Count; i++)
{
    // this[] { get } is present, as ReadOnlyCollection<T> implements IList<T>:
    var element = immutable[i]; // Works

    // this[] { set } has to be present, as it is required by IList<T>, but it
    // will throw a NotSupportedException:
    immutable[i] = element; // Exception!
}

// ReadOnlyCollection<T> implements IEnumerable<T>, of course:
foreach (var character in immutable)
{
}

// LINQ works fine; idem
var lowercase =
    from c in immutable
    where c >= 'a' && c <= 'z'
    select c;

// You can always evaluate IEnumerable<T> implementations to arrays with LINQ:
var mutableCopy = immutable.ToArray();
// mutableCopy is: new[] { 'a', 'A', 'b', 'B', 'c', 'C' }
var lowercaseArray = lowercase.ToArray();
// lowercaseArray is: new[] { 'a', 'b', 'c' }

추가해야 할 유일한 것은 배열입니다 암시합니다 돌연변이. 함수에서 배열을 반환 할 때 고객 프로그래머에게 물건을 변경할 수 있고 변경해야한다고 제안합니다.

Matt의 답변에 따르면, Ilist는 배열에 대한 완전한 추상 인터페이스이므로 추가, 제거 등을 허용합니다. Lippert가 불변성이 필요한 ienumerable의 대안으로 제안하는 이유는 확실하지 않습니다. (편집하다: ILIST 구현은 이러한 종류의 것을 좋아한다면 이러한 돌연변이 방법에 대해 예외를 제외 할 수 있기 때문입니다).

아마도 목록에있는 항목에도 변이 된 상태가있을 수 있다는 점을 명심해야 할 또 다른 사항이있을 수 있습니다. 발신자가 해당 상태를 수정하는 것을 실제로 원하지 않으면 몇 가지 옵션이 있습니다.

목록의 항목이 불변인지 확인하십시오 (예에서와 같이 문자열은 불변).

모든 것의 깊은 클론을 반환하십시오. 따라서 어쨌든 배열을 사용할 수 있습니다.

항목에 대한 Reshonly 액세스를 제공하는 인터페이스를 반환합니다.

interface IImmutable
{
    public string ValuableCustomerData { get; }
}

class Mutable, IImmutable
{
    public string ValuableCustomerData { get; set; }
}

public class Immy
{
    private List<Mutable> _mutableList = new List<Mutable>();

    public IEnumerable<IImmutable> ImmutableItems
    {
        get { return _mutableList.Cast<IMutable>(); }
    }
}

iimmutable 인터페이스에서 액세스 할 수있는 모든 값은 그 자체가 불변 (예 : 문자열)이어야합니다.

당신이 희망 할 수있는 최선은 자신의 컬렉션을 확장하기 위해 기존 컬렉션을 확장하는 것입니다. 가장 큰 문제는 모든 통화가 새 컬렉션을 반환해야하기 때문에 기존 컬렉션 유형과 다르게 작동해야한다는 것입니다.

체크 아웃하고 싶을 수도 있습니다 내 대답 객체에 컬렉션 노출에 대한 더 많은 아이디어에 대한 비슷한 질문에.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top