1

I have such a funny question.

I have the following architecture:

For example, Manager class is implemented like this:

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;
        }
    }
}

And 'factory client' that looks like this:

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;
        }
    }        
}

And finally I have some test code:

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);
    }

Line ((Employee)this.company[SalesPerson01.GetHashCode().ToString()]).Subordinates.Add(this.company[SalesPerson02.GetHashCode().ToString()]); throws NullReferenceExeption. In the this.company[SalesPerson02.GetHashCode().ToString()] indexer returns IEmployee interface but not a class instance. Am I right? And if it is so how do I fix that?

5
  • 9
    Holy wall of code batman. Pare it down to something less than 1000 lines of code and I'll take a look. Commented Mar 15, 2011 at 20:53
  • Geez yea. Auto-generated diagrams don't help. Commented Mar 15, 2011 at 20:54
  • Whats with the GetHashCode().... Commented Mar 15, 2011 at 20:55
  • 1
    Split up that line into Employee a = this.company[SalesPerson01.GetHashCode().ToString()]) etc... and see wich var is null Commented Mar 15, 2011 at 20:55
  • Does the exception indicate which member is null? My vote is that this.company is null, but it's impossible to tell. Commented Mar 15, 2011 at 20:56

3 Answers 3

3

I don't see anywhere that you are initializing the Subordinates member, so I suspect that it still has the default value which is null (not the empty list). The fix is to initialize it to an empty list in the constructor:

public Manager(Person person, DateTime hiredate) : base(person, hiredate)
{
    Subordinates = new List<Interface.IEmployee>();
}
Sign up to request clarification or add additional context in comments.

4 Comments

Don't auto-implemented properties initialize its backing field?
@helicera: Yes - both auto-implemented properties and plain fields are automatically initialized to the default value for the type. The problem is that the default value for reference types is null, which is obviously not what you were expecting.
@helicera - yes they do. To their default value. Which is null for reference types.
Thank you very much! I didn't think about that) And sorry for the ton of code, I just couldn't formulate the problem in few words)
0

it seems you're putting in Person but then casting to Employee which are unrelated classes

Comments

0

indexer returns IEmployee interface but not a class instance. Am I right?

You don't right indexer must return instance, create instance from interface impossible.

I think this.company[SalesPerson02.GetHashCode().ToString()] returns null cause you don't add SalesPerson02 instance to your company object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.