진지하게, API에서 목록 사용을 중지하십시오.

4061 단어 csharpdotnet
List<T>는 컬렉션에, StringBuilder는 문자열에 해당합니다. 컬렉션을 명령적으로 구축하기 위한 메커니즘입니다. List<T>는 다음과 같은 용도로 설계되었습니다.

IReadOnlyList<Element> GetElements(IReadOnlyCollection<Element> inputElement) 
{
    var list = new List<Element>();
    foreach(var inputElem in inputElements)
    {
        if (...) 
        {
            list.Add(inputElem);
        }
    }
    return list;
}

List<T>는 함수 시그니처인 API에 표시되지 않는다는 점에 유의하십시오. 이는 구현 세부 사항, 메커니즘입니다. API가 말하는 것은 나에게 모든 종류의 컬렉션을 제공하고 나는 당신에게 또 다른 한정된 인덱스 컬렉션을 제공할 것입니다. 호출자는 이를 이해하기 위해 구현을 읽을 필요가 없습니다.

입력 요소를 List<T> 로 바꾸면 어떻게 되는지 봅시다.

IReadOnlyList<Element> GetElements(List<Element> inputElement) 


이것은 이제 혼란스럽고 제한적인 함수 서명입니다. 컬렉션을 반환하지만 입력 컬렉션의 요소를 추가, 제거 또는 변경할 수도 있습니다. 그래? 발신자는 모릅니다. 그는 코드를 읽어야 합니다. 즉, 우리 API는 더 이상 명확한 추상화가 아닙니다. 또한 호출자는 Array , ImmutableArray 또는 다른 컬렉션을 전달할 수 없습니다. 이러한 컬렉션은 실제로 우리의 목적에 완벽하게 잘 작동합니다.

해당 입력 인수를 수정하려는 경우가 아니면 List<T>를 입력 인수로 사용하지 마십시오. 이 경우 함수는 아마도 void (또는 비동기인 경우 Task )를 반환해야 합니다.

void AddElements(List<T> collection); // this does make sense


이제 다른 경우인 반환 유형을 살펴보겠습니다. 이것은 무엇을 의미할까요?

List<Element> GetElements(IReadOnlyCollection<Element> inputElement) 


이것은 제한적이지는 않지만 똑같이 혼란스럽습니다. 이 함수는 호출자가 수정할 수 있는 컬렉션을 반환합니다. 왜요? 함수는 나중에 변경 사항을 관찰할 수 있도록 어딘가에 참조를 저장합니까? 아니면 사용하는 동안 수정합니까? 다시 말하지만 이것은 읽을 필요가 없을 때 구현을 읽으라는 메시지를 표시하는 이상한 API 설계일 뿐입니다.

반환해야 할 합당한 이유를 찾기가 어렵습니다List<T>. 내부 변경 가능한 컬렉션이 있는 경우 예기치 않게 수정될 수 있는 외부 세계와 공유하는 것은 확실히 나쁜 생각입니다. 변경 가능한 상태는 로컬로 유지하는 것이 가장 좋습니다.

엄밀히 말하면 반환IReadOnlyList<T>도 불변성을 보장하지는 않지만 해당 방향으로 강력한 메시지를 보냅니다. 엄밀히 말하면 올바른 반환 유형은 ImmutableArray<T> 또는 ImmutableList<T> 입니다. 나는 여전히 울타리에 있습니다. 어떤 이유에서든 라이브러리는 IReadOnly 보다 System.Collections.Immutable 인터페이스에 더 끌리는 것 같습니다.

좋은 웹페이지 즐겨찾기