2016-06-17 4 views
0

클래스 속성에서 코드 적용 범위를 확인할 때 발견 된 시나리오가 있습니다. 속성이 List < T>이고 초기화 프로그램이 사용되면 set 메서드가 호출 된 것으로 나타나지 않습니다. 이것은 문자열이나 int와 같은 다른 유형에는 해당되지 않습니다. 코드 커버리지는 set call을 보여주지 않으며, set의 breakpoint에도 영향을주지 않습니다.속성 초기화가 목록 집합을 호출하지 않습니다. <T>

예 클래스 :

public class ContainerClass 
{ 
    public string Text { get; set; } 
    public List<Item> Items { get; set; } 
} 

다음과 같은 텍스트에 set 메소드가 호출되고, 이니셜 라이저를 사용하여, 코드 커버리지 레지스터하지만 항목의 설정 방법은하지 않습니다, 나는 왜 궁금 :

var arrange = new ContainerClass 
{ 
    Text = "value", 
    Items = { new Item() } 
}; 

편집 : 목록이 올바르게 지정되어 있고 테스트 할 수 있지만 실제 설정 방법을 따르는 것으로 보입니다.

나는 새 목록을 지정할 때 흥미롭게도, 그것은 전화를받을 않습니다 당신이 경우,

var arrange = new ContainerClass 
{ 
    Text = "SomeValue" 
}; 
arrange.Items.Add(new Item(){Prop=Value}); 

또는 그런 다음

public class ContainerClass 
{ 
    public string Text { get; set; } 
    public List<Item> Items { get; set; } 

    public ContainerClass() 
    { 
     Items = new List<Item>(); 
    } 
} 

:

var arrange = new ContainerClass 
{ 
    Items = new List<Item> { new Item() } 
}; 
+1

정확한 초기화 방법은 마지막 예입니다. 다른 버전의 의미가 무엇인지 모르겠습니다. –

+3

목록이 나에게 할당되지 않아 NullReferenceException이 발생합니다. – BoltClock

+2

§7.6.10.2 "등호 뒤에 콜렉션 이니셜 라이저를 지정하는 멤버 이니셜 라이저는 필드 또는 속성에 새 콜렉션을 할당하는 대신 참조되는 콜렉션에 이니셜 라이저에 제공된 요소를 추가합니다 필드 또는 속성에 의해. " 코드가 제대로 작동하려면 목록이 초기화되어 있어야합니다. 예를 들어 제대로 실행되지 않습니다. – BoltClock

답변

3

다음과 같은 텍스트에 대한 set 메소드를 호출하고, 코드 커버리지에 등록하지만, 항목의 설정 방법은하지 않습니다, 나는 왜 궁금하고, 이니셜 라이저를 사용하여 :

컬렉션 초기화 프로그램이 호출 될 때 항목 목록이 실제로 초기화되지 않기 때문입니다. 스펙의 섹션 7.6.10.2에서 :

등호 기호 후 컬렉션 이니셜 라이저를 지정하는 멤버 이니셜 라이저가 포함 된 컬렉션을 초기화입니다. 새 컬렉션을 필드 또는 속성에 할당하는 대신 초기화 프로그램에서 제공 한 요소가 필드 또는 속성에서 참조하는 컬렉션에 추가됩니다.

이것은 컬렉션 초기화 프로그램이 컬렉션이 이미 인스턴스화되었다고 가정한다는 것을 의미합니다 (이는 개체 이니셜 라이저 외부에서도 마찬가지입니다). 컬렉션 이니셜 라이저는 일련의 .Add() 호출 일뿐입니다.

오류없이 코드를 실행하려면 항목이 이미 초기화되어 있어야합니다. 이 일이 어느 속성 선언 그 자체로 (이 자동 구현 속성을의 가정) 할 수 :

public class ContainerClass 
{ 
    public string Text { get; set; } 
    public List<Item> Items { get; set; } = new List<Item>(); 
} 

또는 (당신은 표시하지 않은 경우) 생성자

:

public class ContainerClass 
{ 
    public string Text { get; set; } 
    public List<Item> Items { get; set; } 

    public ContainerClass() 
    { 
     Items = new List<Item>(); 
    } 
} 

그렇지 않으면 코드가 컬렉션 초기화 프로그램을 평가하려고 할 때 NullReferenceException을 throw합니다.

Setter가 항목에 대해 호출되지 않는다는 사실을 기반으로 속성 선언 (또는 자동 구현 속성이 아닌 경우 해당하는 입력란)에서 초기화되었을 가능성이 큽니다. 생성자에서 초기화 되었다면 여전히 setter가 호출되었을 것입니다.

실제로 두 번째 항목에 새 목록을 할당 했으므로 두 번째 예에서는 setter가 호출됩니다.

+0

당신이 맞습니다, 나는 = new List ()을 속성 선언 다음에 포함 시켰다고보고 싶었습니다. 당신의 설명은 완벽합니다. 고마워요. –

0

당신도 할 수 명시된대로 생성자를 사용하지 말고 다음과 같이 목록을 초기화 할 수 있습니다.

var arrange = new ContainerClass 
{ 
    Items = new List<Item>(){ new Item(){Prop=Value} } 
}; 
+0

생성자 내에서 초기화하면 질문의 첫 번째 초기화 예제가 작동하기에 충분하지만 수정할 필요가 없습니다. 상기 및/또는 예는 상기 질문에서의 두번째 예의 단지 재 설명 일 뿐이다. – BoltClock

+0

사실,이 예는 생성자가없는 경우에 해당합니다. 그것을 반영하도록 업데이트하겠습니다. – Phil