[C#] IList 사용시기 및 List 사용시기

나는 IList가 인터페이스이고 List가 구체적인 유형이라는 것을 알고 있지만 여전히 각 유형을 언제 사용 해야할지 모르겠습니다. 내가 지금하고있는 일은 인터페이스를 사용하는 Sort 또는 FindAll 메서드가 필요하지 않은 것입니다. 내가 맞아? 인터페이스 또는 콘크리트 유형을 언제 사용할지 결정하는 더 좋은 방법이 있습니까?



답변

내가 따르는 두 가지 규칙이 있습니다.

  • 작동하는 가장 기본적인 유형을 수락하십시오
  • 사용자에게 필요한 가장 풍부한 유형을 반환

따라서 컬렉션을 취하는 함수 나 메서드를 작성할 때는 List가 아니라 IList <T>, ICollection <T> 또는 IEnumerable <T>를 사용하도록 작성하십시오. System.Object도 T 일 수 있기 때문에 이종 목록에도 일반 인터페이스가 작동합니다. 이렇게하면 스택이나 다른 데이터 구조를 사용하기로 결정한 경우 골치 아프게됩니다. 함수에서해야 할 모든 것이 foreach이면 IEnumerable <T> 만 있으면됩니다.

반면, 함수에서 객체를 반환 할 때는 사용자가 캐스트하지 않고도 가장 풍부한 작업 집합을 사용자에게 제공하려고합니다. 이 경우 내부적으로 List <T>이면 복사본을 List <T>로 반환하십시오.


답변

FxCop에서 확인한 Microsoft 지침은 공용 API에서 List <T> 사용을 권장하지 않습니다. IList <T>를 선호하십시오.

또한 이제는 거의 항상 1 차원 배열을 IList <T>로 선언하므로 Array.Length 대신 IList <T> .Count 속성을 일관되게 사용할 수 있습니다. 예를 들면 다음과 같습니다.

public interface IMyApi
{
    IList<int> GetReadOnlyValues();
}

public class MyApiImplementation : IMyApi
{
    public IList<int> GetReadOnlyValues()
    {
        List<int> myList = new List<int>();
        ... populate list
        return myList.AsReadOnly();
    }
}
public class MyMockApiImplementationForUnitTests : IMyApi
{
    public IList<int> GetReadOnlyValues()
    {
        IList<int> testValues = new int[] { 1, 2, 3 };
        return testValues;
    }
}


답변

사람들이 항상 간과하는 중요한 것이 있습니다.

일반 배열을 IList<T>매개 변수 를 허용하는 것으로 전달한 다음 호출 IList.Add()하여 런타임 예외를 수신 할 수 있습니다 .

Unhandled Exception: System.NotSupportedException: Collection was of a fixed size.

예를 들어 다음 코드를 고려하십시오.

private void test(IList<int> list)
{
    list.Add(1);
}

다음과 같이 호출하면 런타임 예외가 발생합니다.

int[] array = new int[0];
test(array);

이는 일반 배열을 사용 IList<T>하여 Liskov 대체 원칙 을 위반 하기 때문에 발생합니다 .

이러한 이유로 전화 IList<T>.Add()를 거는 경우 List<T>대신을 (를) 요구하는 것이 좋습니다 IList<T>.


답변

나는 매개 변수를 취했지만 반환하지 않는 Lee의 조언에 동의합니다.

인터페이스를 반환하도록 메서드를 지정하면 소비하는 메서드를 모르더라도 나중에 정확한 구현을 자유롭게 변경할 수 있습니다. 나는 List <T>에서 변경할 필요가 없다고 생각했지만 나중에 추가 기능을 위해 사용자 지정 목록 라이브러리를 사용하도록 변경해야했습니다. IList <T> 만 반환했기 때문에 라이브러리를 사용하는 사람들은 코드를 변경하지 않아도됩니다.

물론 외부에서 볼 수있는 메소드 (공용 메소드)에만 적용하면됩니다. 나는 내부 코드에서도 개인적으로 인터페이스를 사용하지만 변경 사항을 변경하면 모든 코드를 직접 변경할 수 있으므로 반드시 필요한 것은 아닙니다.


답변

IEnumerable
목적에 가장 적합한 유형을 사용하지 않아야합니다.
IEnumerable보다 구체적이지 않습니다 IList. 컬렉션의 항목을 반복 할 때
사용 IEnumerable합니다.

IList가
IList 구현 IEnumerable합니다. 컬렉션에 인덱스로 액세스하고 요소를 추가 및 삭제하는 등의 작업이 필요할 때
사용해야합니다 IList.


List구현 목록IList .


답변

항상 가장 낮은 기본 유형을 사용하는 것이 가장 좋습니다. 이를 통해 인터페이스의 구현 자 또는 메소드의 소비자에게이면에서 원하는 것을 사용할 수있는 기회가 제공됩니다.

컬렉션의 경우 가능한 경우 IEnumerable을 사용하는 것이 좋습니다. 이것은 가장 융통성이 있지만 항상 적합하지는 않습니다.


답변

단일 메소드 내에서 (또는 경우에 따라 단일 클래스 또는 어셈블리에서) 작업 중이고 외부에서 아무도 수행중인 작업을 보지 못하는 경우에는 전체 목록을 사용하십시오. 그러나 메소드에서 목록을 반환 할 때와 같이 외부 코드와 상호 작용하는 경우 특히 특정 구현에 자신을 연결하지 않고 인터페이스를 선언하려고합니다. 특히 나중에 코드. 구체적인 유형으로 시작하고 동일한 인터페이스를 사용하더라도 다른 유형으로 변경하기로 결정한 경우 인터페이스 또는 추상 기본 유형으로 시작하지 않으면 다른 사람의 코드가 손상됩니다.