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 NullReferenceExeptionthis.company[SalesPerson02.GetHashCode().ToString()]インデクサーはIEmployeeインターフェイスを返しますが、クラスインスタンスは返しません。私は正しい?そしてもしそうなら、私はそれをどのように修正するのですか?

+9

コードバットマンの聖なる壁。それを1000行未満のコードに分解してみてください。 – RQDQ

+0

さようなら。自動生成された図は役に立ちません。 –

+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

インデクサがIEmployeeインターフェイスを返しますがない無関係のクラスであるあなたは人を入れたが、その後、従業員にキャストしているようですクラスインスタンス私は正しい?

右インデクサーはインスタンスを返さなければなりません。インターフェイスからインスタンスを作成できません。

私はthis.company [SalesPerson02.GetHashCode()。ToString()]があなたの会社オブジェクトにSalesPerson02インスタンスを追加しないため、nullを返します。

関連する問題