【问题标题】:Getting NullReferenceException获取 NullReferenceException
【发布时间】:2011-03-15 20:51:30
【问题描述】:

我有一个有趣的问题。

我有以下架构:

例如,Manager类是这样实现的:

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()]); 抛出 NullReferenceExeption。在this.company[SalesPerson02.GetHashCode().ToString()] 索引器中返回IEmployee 接口但不是类实例。我对吗?如果是这样,我该如何解决?

【问题讨论】:

  • 代码蝙蝠侠的圣墙。把它缩减到少于 1000 行代码,我来看看。
  • 天啊,是的。自动生成的图表没有帮助。
  • GetHashCode() 是怎么回事....
  • 将该行拆分为Employee a = this.company[SalesPerson01.GetHashCode().ToString()]) 等...并查看哪个var为空
  • 异常是否表示哪个成员为空?我的投票是 this.company 为空,但无法判断。

标签: c# list interface nullreferenceexception


【解决方案1】:

我没有看到您正在初始化下属成员的任何地方,所以我怀疑它仍然具有默认值 null不是空列表)。修复方法是在构造函数中将其初始化为一个空列表:

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

【讨论】:

  • 自动实现的属性不会初始化其支持字段吗?
  • @helicera:是的 - 自动实现的属性和普通字段都会自动初始化为类型的默认值。问题是引用类型的默认值是null,这显然不是你所期望的。
  • @helicera - 是的。到他们的默认值。引用类型为 null。
  • 非常感谢!我没有考虑过)对于大量的代码,我只是无法用几句话来表述问题)
【解决方案2】:

看来你是在放入 Person 但然后投射到 Employee 是不相关的类

【讨论】:

    【解决方案3】:

    indexer 返回 IEmployee 接口,但不是类实例。我说的对吗?

    你没有正确索引器必须返回实例,从接口创建实例是不可能的。

    我认为 this.company[SalesPerson02.GetHashCode().ToString()] 返回 null 因为您没有将 SalesPerson02 实例添加到您的公司对象。

    【讨论】:

      猜你喜欢
      • 2018-07-06
      • 1970-01-01
      • 2021-01-06
      • 2016-03-30
      • 2016-07-20
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多