2011-03-15 7 views
1

재미있는 질문이 있습니다. NullReferenceException 받기

는 예를 들어, 관리자 클래스는 다음과 같이 구현됩니다 :

나는 다음과 같은 구조를 가지고

public sealed class Manager : Interface.Abstract.Employee 
{ 
    private Interface.IEmployee chief = null; 
    private readonly Decimal bonuslimit = Convert.ToDecimal(0.4F * Convert.ToSingle(BaseSalary)); 

    public Manager(Person person, DateTime hiredate) 
    : base(person, hiredate) 
    { 
    } 

    public override List<Interface.IEmployee> Subordinates 
    { 
     get; 
     set; 
    } 
    public override Interface.IEmployee Chief 
    { 
     get 
     { 
      return this.chief; 
     } 
     set 
     { 
      //if(value is Associate) 
      //{      
      // throw new SystemException("Associate can't be a chief"); 
      //} 
      this.chief = value; 
     } 
    } 
    public override Decimal Salary 
    { 
     get 
     { 
      var actualbonus = Convert.ToDecimal(0.01F * Convert.ToSingle(this.YearsSinceHired * BaseSalary)); 
      var bonus = (actualbonus > bonuslimit) ? bonuslimit : actualbonus; 
      var additional = 0M; 

      if(this.HasSubordinates) 
      { 
       foreach(Interface.Abstract.Employee employee in this.Subordinates) 
       { 
        if(employee is Sales) 
        { 
         additional += employee.Salary; 
        } 
       } 
      } 
      return Convert.ToDecimal(Convert.ToSingle(additional) * 0.005F) + BaseSalary + bonus; 
     } 
    } 
} 

그리고 다음과 같다 '공장 클라이언트 :

public class EmployeeFactoryClient 
{ 
    private IDictionary<String, IEmployee> employees = new Dictionary<String, IEmployee>();    

    public EmployeeFactoryClient() 
    { 
     this.Factory = new EmployeeFactory();    
    } 
    public EmployeeFactoryClient(IEmployeeFactory factory) 
    { 
     this.Factory = factory;    
    } 
    public IEmployeeFactory Factory { get; set; } 

    public void HireEmployee(Person person, String type, String code) 
    { 
     this.employees.Add(
      new KeyValuePair<String, IEmployee>(
       code, 
       this.Factory.Create(person, type, DateTime.Now) 
      ) 
     ); 
    } 
    public void DismissEmployee(String code) 
    { 
     this.employees.Remove(code); 
    } 
    public IEmployee GetEmployee(String code) 
    { 
     return this.employees[code]; 
    } 
    public IEmployee this[String index] 
    { 
     get { return this.employees[index]; } 
     private set { this.employees[index] = value; } 
    } 

    public Decimal TotalSalary 
    { 
     get 
     { 
      var result = 0M; 
      foreach(var item in this.employees) 
      { 
       result += item.Value.Salary; 
      } 
      return result; 
     } 
    }   
} 

을 마지막으로 테스트 코드가 있습니다.

public void SalaryTest() 
    { 
     #region [Persons]    
     var SalesPerson01 = new Person 
     { 
      Birthday = new DateTime(1980, 11, 03), 
      Forename = "Corey", 
      Surname = "Black", 
      Gender = SexType.Female 
     }; 
     var SalesPerson02 = new Person 
     { 
      Birthday = new DateTime(1980, 11, 03), 
      Forename = "John", 
      Surname = "Travis", 
      Gender = SexType.Male 
     }; 
     #endregion 

     this.company.HireEmployee(SalesPerson01, "Sales", SalesPerson01.GetHashCode().ToString()); 
     ((Employee)this.company[SalesPerson01.GetHashCode().ToString()]).YearsSinceHired = 10; 

     this.company.HireEmployee(SalesPerson02, "Sales", SalesPerson02.GetHashCode().ToString()); 
     ((Employee)this.company[SalesPerson02.GetHashCode().ToString()]).YearsSinceHired = 3;    

     /////////////////////////////////////////////////////////////////// 
     ((Employee)this.company[SalesPerson01.GetHashCode().ToString()]).Subordinates.Add(
      this.company[SalesPerson02.GetHashCode().ToString()] 
     ); 

     Assert.AreEqual(1405M, this.company.TotalSalary); 
    } 

라인 ((Employee)this.company[SalesPerson01.GetHashCode().ToString()]).Subordinates.Add(this.company[SalesPerson02.GetHashCode().ToString()]); throws NullReferenceExeption. this.company[SalesPerson02.GetHashCode().ToString()] 인덱서에서는 IEmployee 인터페이스를 반환하지만 클래스 인스턴스는 반환하지 않습니다. 내가 맞습니까? 그리고 만약 그렇다면 어떻게 수정해야합니까?

+9

코드 배트맨의 신성한 벽. 1000 줄 이하의 코드를 작성한 다음 살펴 보겠습니다. – RQDQ

+0

Geez yea. 자동 생성 다이어그램은 도움이되지 않습니다. –

+0

GetHashCode() .... 무엇을할까요? –

답변

3

는 난 아무데도 당신이 부하 직원 멤버를 초기화하는 것을 볼 수 없습니다, 그래서 나는 여전히 null (하지 빈리스트) 인 디폴트 값이 있는지 생각한다. 수정 생성자의 빈 목록으로 초기화하는 것입니다

public Manager(Person person, DateTime hiredate) : base(person, hiredate) 
{ 
    Subordinates = new List<Interface.IEmployee>(); 
} 
+0

+1이 혼란에 대답하기위한 노력. –

+0

자동 구현 된 속성이 지원 필드를 초기화하지 않습니까? – lexeme

+2

@helicera : 예 - 자동 구현 된 속성과 일반 필드가 모두 해당 유형의 기본값으로 자동 초기화됩니다. 문제는 참조 유형의 기본값이 'null'이며, 이는 분명히 사용자가 기대하지 않았던 것입니다. –

0

당신이 사람에 넣어하지만있는 직원에 캐스팅 관련이없는 클래스

0

인덱서있어 보이는 것은 IEmployee 인터페이스를 반환하지만 클래스 인스턴스. 내가 맞습니까?

오른쪽 인덱서가 인스턴스를 반환해야하며 불가능 인터페이스에서 인스턴스를 만듭니다.

SalesPerson02 인스턴스를 회사 개체에 추가하지 않았으므로 this.company [SalesPerson02.GetHashCode(). ToString()]이 null을 반환한다고 생각합니다.

관련 문제