문제

코드는 다음과 같습니다.

namespace Test
{
    public interface IMyClass
    {
        List<IMyClass> GetList();
    }

    public class MyClass : IMyClass
    {
        public List<IMyClass> GetList()
        {
            return new List<IMyClass>();
        }
    }
}

코드 분석을 실행하면 다음 권장 사항이 있습니다.

경고 3 CA1002 : Microsoft.Design : 'imyclass.getList ()에서'list '를 변경하여 수집, readOnlyCollection 또는 KeyEdCollection을 사용합니다.

이것을 어떻게 고쳐야하고 여기서 좋은 관행은 무엇입니까?

도움이 되었습니까?

해결책

"왜"가 아닌 이유에 대한 "왜"에 대답하려면 List<T>, 그 이유는 미래 방지 및 API 단순성입니다.

미래 방지

List<T> 서브 클래싱으로 쉽게 확장 할 수 있도록 설계되지 않았습니다. 내부 구현에 빠르게 설계되었습니다. 당신은 그것의 방법이 가상이 아니라는 것을 알 수 있으므로 재정의 할 수 없으며 그것의 고리가 없습니다. Add/Insert/Remove 운영.

즉, 미래에 컬렉션의 동작을 변경 해야하는 경우 (예 : 사람들이 추가하려고하는 널 개체를 거부하거나 클래스 상태 업데이트와 같은 이런 일이 발생할 때 추가 작업을 수행하기 위해) 유형을 변경해야합니다. 서브 클래스로 돌아갈 수있는 컬렉션의 컬렉션은 인터페이스가 깨지는 인터페이스 변경입니다 (물론 NULL을 허용하지 않는 것과 같은 것들의 의미를 변경하는 것도 인터페이스 변경 일 수도 있지만 내부 클래스 상태를 업데이트하는 것과 같은 것은 그렇지 않습니다).

따라서 Collection<T> 또는 다음과 같은 인터페이스 IList<T>, ICollection<T> 또는 IEnumerable<T> 소비자 코드를 깨뜨리지 않고 내부 구현을 다른 수집 유형으로 변경할 수 있습니다.

API 단순성

List<T> 다음과 같은 많은 유용한 작업이 포함되어 있습니다 BinarySearch, Sort 등등. 그러나 이것이 당신이 노출시키는 컬렉션이라면, 당신은 소비자가 아니라 목록의 의미를 제어 할 가능성이 높습니다. 따라서 수업에는 내부적으로 이러한 작업이 필요할 수 있지만, 수업의 소비자가 전화를 걸기를 원하거나 심지어 전화해야 할 가능성은 거의 없습니다.

따라서 더 간단한 컬렉션 클래스 또는 인터페이스를 제공하면 API 사용자가 보는 회원 수를 줄이고 쉽게 사용할 수 있습니다.

다른 팁

개인적으로 콘크리트 컬렉션이 아닌 인터페이스를 반환하도록 선언합니다. 실제로 목록 액세스를 원한다면 사용하십시오 IList<T>. 그렇지 않으면 고려하십시오 ICollection<T> 그리고 IEnumerable<T>.

그것은 주로 목록 개체를 직접 조작 할 것을 노출시키는 대신 자신의 구현을 추상화하는 것입니다.

다른 물체 (또는 사람)가 객체의 상태를 직접 수정하도록하는 것은 좋은 관행이 아닙니다. 속성 getters/setters를 생각하십시오.

수집 -> 일반 수집 용
readonlycollection-> 수정해서는 안되는 컬렉션의 경우
KeyEdCollection-> 대신 사전을 원할 때.

수업을 수정하는 방법은 수업을 원하는 것과 getList () 메소드의 목적에 따라 다릅니다. 정교 해 줄 수 있습니까?

이러한 종류의 경우 나는 보통 필요한 최소한의 구현을 노출 시키려고 노력합니다. 소비자가 실제로 목록을 사용하고 있음을 알 필요가 없다면 목록을 반환 할 필요가 없습니다. Microsoft로 반환하면 컬렉션을 제안하면 클래스 소비자의 목록을 사용하고 있다는 사실을 숨기고 내부 변경으로부터 격리하십시오.

나는 아무도 "왜"부분에 대답했다고 생각하지 않습니다 ... 그래서 여기에 간다. "당신"이 "왜"해야하는 이유는 Collection<T> 대신 a List<T> 당신이 노출하는 경우 a List<T>, 그러면 객체에 액세스하는 사람은 누구나 목록의 항목을 수정할 수 있습니다. 반면 Collection<T> 자신만의 "추가", "제거"등을 만들고 있음을 나타냅니다.

아마도 당신은 아마도 자신을 위해 인터페이스를 코딩하고 있기 때문에 걱정할 필요가 없을 것입니다. 다음은 의미가있는 또 다른 예입니다.

공개 배열이있는 경우 예 :

public int[] MyIntegers { get; }

당신은 아무도 값을 엉망으로 만들 수없는 "접근"만 있기 때문에 그렇지 않다고 생각할 것입니다. 그러나 그것은 사실이 아닙니다. 누구나 다음과 같이 내부의 값을 변경할 수 있습니다.

someObject.MyIngegers[3] = 12345;

개인적으로, 나는 그냥 사용할 것입니다 List<T> 대부분의 경우에. 그러나 무작위 개발자에게 줄 수있는 클래스 라이브러리를 설계하고있는 경우 객체의 상태에 의존해야합니다 ... 그러면 나만의 컬렉션을 만들고 거기에서 잠그고 싶을 것입니다. )

이 질문 이후 오랜 시간이 지났지 만 추가 할 것이 있습니다.

목록 유형에서 파생 된 경우 List<T> 대신에 Collection<T>, 보호 된 가상 방법을 구현할 수 없습니다 Collection<T> 구현. 이것이 의미하는 바는 도출 된 유형이 목록에 대한 수정이 이루어지면 응답 할 수 없다는 것입니다. 이 때문입니다 List<T> 항목을 추가하거나 제거 할 때 알고 있다고 가정합니다. 알림에 대한 응답을 할 수 있다는 것은 오버 헤드이므로 List<T> 그것을 제공하지 않습니다.

외부 코드가 컬렉션에 액세스 할 경우 항목이 추가되거나 제거 될 때를 제어하지 않을 수 있습니다. 그러므로 Collection<T> 목록이 언제 수정되었는지 알 수있는 방법을 제공합니다.

나는 같은 것을 반환하는 데 아무런 문제가 없습니다

this.InternalData.Filter(crteria).ToList();

연결이 끊어진 경우 복사 내부 데이터 또는 데이터 쿼리의 분리 된 결과 - 안전하게 반환 할 수 있습니다. List<TItem> 구현 세부 정보를 노출시키지 않고 편리한 방식으로 리턴 된 데이터를 사용할 수 있습니다.

그러나 이것은 내가 기대하는 소비자 유형에 달려 있습니다. 데이터 그리드와 같은 것이라면 반환하는 것을 선호합니다. IEnumerable<TItem> 복사 된 항목 목록이 될 것입니다 어쨌든 대부분의 경우 :)

컬렉션 클래스는 실제로 구현 세부 사항 및 기타 기능을 숨기기 위해 다른 컬렉션 주변의 래퍼 클래스 일뿐입니다. 나는 이것이 객체 지향 언어로 코딩 패턴을 숨기는 속성과 관련이 있다고 생각합니다.

나는 당신이 그것에 대해 걱정해서는 안된다고 생각하지만, 코드 분석 도구를 정말로 기쁘게하고 싶다면 다음을 수행하십시오.

//using System.Collections.ObjectModel;

Collection<MyClass> myCollection = new Collection<MyClass>(myList);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top