为什么这段代码抛出了ArgumentNullException?

时间:2010-02-14 13:51:09

标签: c# .net

我全部使用这个代码模式,只有在这个特定的属性中,当尝试为它赋值时(即调用setter),会抛出ArgumentNullException。对象为null是isLoggedInLock,因此它似乎在调用setter之前尚未实例化。 Wat错了?

编辑:我注释掉OnPropertyChanged方法,以避免混淆。仍然抛出异常。我能想到的另一件事是更新是在另一个线程中完成的,而不是UI线程。

EDIT2:我在非静态构造函数中实例化了isLoggedInLock,但仍抛出了异常。一些非常奇怪的事情正在发生。我会进一步调查。

最后编辑:道歉:我遗漏了解决方案的关键:[DataMember]属性。该对象通过反序列化而生效。这会跳过默认构造函数和isLoggedInLock的静态初始化。通过使用[DataMember]属性装饰isLoggedInLock或通过在装有[OnDeserialzed]属性的方法中对其进行实例化,问题就会消失!

谢谢一堆,第一个更新他的答案将获得积分! ; - )

    [DataMember]
    private bool isLoggedIn;
    private readonly object isLoggedInLock=new object();
    public bool IsLoggedIn
    {
        get
        {
            lock (isLoggedInLock)
            {
                return isLoggedIn; 
            }
        }
        set
        {
            lock (isLoggedInLock)
            {
                isLoggedIn = value;
                //OnPropertyChanged("IsLoggedIn");
            }
        }
    }

5 个答案:

答案 0 :(得分:4)

在您发布的代码中抛出ArgumentNullException的唯一原因是,当执行lock语句时,isLoggedInLock为null。因此,除非你明确地将isLoggedInLock设置为其他地方的null(并且这只能在构造函数中,因为该字段是只读的),所以你的假设是正确的:

  似乎它还没有   在setter之前实例化   称为

字段将按照它们被声明的顺序进行初始化,因此如果你有一个字段初始化高于调用访问IsLoggedIn属性的成员,这将在isLoggedInLock初始化之前发生。

如果从异常中查看堆栈跟踪,应该很容易弄清楚正在发生的事情。

答案 1 :(得分:3)

最常见的原因,从10秒的代码看,是OnPropertyChanged。

我从命名中猜测它引发了一个事件。我们能看到这种方法的代码吗?有可能是在没有先进行空检查来检查有人订阅的情况下调用事件处理程序。

[编辑 - 抱歉没有读到你认为isLoggedInLock是罪魁祸首]

你确定它是isLoggedInLock - 因为看起来没有多少范围是空的。由于它被标记为只读,因此在方法的其他地方不可能将其设置为null。

这是受影响代码的准确表示吗?绝对不是属性是静态的,还是有些差别?

答案 2 :(得分:2)

你有静态构造函数吗? (它是否使用IsLoggedIn?)

答案 3 :(得分:2)

可能是一个类的字段为null,即使它在构造函数中初始化时:当类通过反序列化生成时,构造函数 not 叫....

答案 4 :(得分:0)

是否可行,反射被设置为“isLoggedInLock”为null?使用FieldInfo.SetValue(),您可以更改只读字段的值。