2016-08-03 2 views
0
namespace TestOOP 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 

    internal sealed class Student 
    { 
     private string name; 
    } 

    internal sealed class Course 
    { 
     private ICollection<Student> students; 

     public ICollection<Student> Students 
     { 
      get { return this.students; } 
      set { this.students = Students; } 
     } 
    } 

    class Program 
    { 
     static void Main() 
     { 
      var course = new Course(); 
      course.Students.Add(new Student()); 
      Console.WriteLine(course.Students.Count()); 
     } 
    } 
} 

그게 내 코드. 그것을 실행할 때 나는 코스에 학생을 추가하려고하는 라인에서 객체의 인스턴스로 설정되지 않은 객체를 얻습니다. 인터페이스를 필드로 사용하는 방법을 설명하는 데 도움이 필요합니다.인터페이스를 필드로 사용하는 방법은 무엇입니까?

internal sealed class Course 
{ 
    readonly List<Student> students = new List<Student>(); 
    public ICollection<Student> Students 
    { 
     get { return this.students; } 
    } 
} 

이것은 Students 속성이 null 결코 있는지 확인합니다, 어떤 코드를 대체 할 수 있습니다 : 수집의 호텔을

+0

특히이 경우 값을 'Students' 속성 (또는 backfield'students')으로 설정하지 않으므로 'null'이고 'Students.Count()'가 throw됩니다. – Sinatr

답변

4

, 그것은 건설 중에를 초기화하고, readonly 게터를 통해 노출하는 좋은 습관이다 다른 인스턴스와 함께 백킹 필드. 그러나 이것은 클래스를 변경할 수 없게 만듭니다. 여전히 Students 컬렉션에서 항목을 추가하고 제거 할 수 있습니다. 당신은 또한 autoimplemented 읽기 전용 속성을 사용할 수 있습니다 C# 6 구문

:

internal sealed class Course 
{ 
    public ICollection<Student> Students { get; } = new List<Student>(); 
} 
+0

목록의 모든 기능을 사용하고 싶지 않으면 추가/제거/계산 만 하시겠습니까? ICollection을 구현할 사용자 지정 클래스를 만들어야합니까? – sirSemite

+0

이 경우 상속 대신 composition을 사용하는 것이 좋습니다. 즉, 'students'를 비공개 필드로 만들고 공용 속성을 완전히 제거한 다음 필요한 공용 메서드 만 공개합니다 (비공개 목록에서 작동). 당신이'ICollection'을 상속했다면, 당신은 그 인터페이스에있는 모든 메소드를 직접 구현해야 할 것입니다. 그러나 이것은 잘못된 접근입니다. * 콜렉션이 변경되었을 때 이벤트를 발생시키는 커스텀'StudentsCollection'을 원하지 않는 한, "코스"는 단순히 "학생 컬렉션"이 아닙니다). – Groo

1

귀하의 문제는 인터페이스하지 않습니다, 그것은 당신이 당신의 변수에 아무것도 지정하지 않는 것이 사실이다.

private ICollection<Student> students; 

이 그것을 수정합니다 :

private ICollection<Student> students = new List<Student>(); 
0

을 당신은 클래스 코스의 생성자 사용 예를 들어, 속성 학생들의 실제 인스턴스를 생성해야합니다

internal sealed class Course 
{ 
    private ICollection<Student> students; 

    public ICollection<Student> Students 
    { 
     get { return this.students; } 
     set { this.students = Students; } 
    } 

    public Course() 
    { 
     this.Students = new List<Student>(); 
    } 
} 

인터페이스를 진짜 클래스에 의해 구현되어야합니다.

관련 문제