为什么这段代码会抛出ArgumentNullException异常?

3

I use this code pattern all over and only in this particular property an ArgumentNullException is thrown when trying to assign a value to it (ie invoking the setter). The object being null is the isLoggedInLock,so it seems that it has not been instantiated before the setter is called. Wat is wrong??

EDIT: I commented out the OnPropertyChanged method to avoid confusion. The exception is still thrown. One other thing I can think of is that the update is done in another thread than the UI thread.

EDIT2: I instantiated the isLoggedInLock in the non-static constructor and still the exception is thrown. Something very strange is going on. I will investigate further.

FINAL EDIT: My apologies: I left out the key to the solution: the [DataMember] Attribute. The object comes into life by being deserialized. This skips the default constructor and the static initialisation of the isLoggedInLock. By adorning the isLoggedInLock with the [DataMember] attribute or by instantiating it in a method adorned with the [OnDeserialzed] attribute the problem goes away!

Thanks a bunch and the first to update his answer will get the points! ;-)

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


OnPropertyChanged 方法中有任何代码吗? - Gary Joynes
1
请捕获异常并发布 ex.ToString() 的结果。 - John Saunders
这是一个“ArgumentNullException”还是一个“NullReferenceException”,就像你标记的那样? - John Saunders
ArgumentNullException,标签不准确。 - Dabblernl
5个回答

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

看起来在setter被调用之前它还没有被实例化

字段将按照声明的顺序进行初始化,因此如果您有一个较高的字段初始化调用了访问IsLoggedIn属性的成员,则会在初始化isLoggedInLock之前发生这种情况。
如果查看异常的堆栈跟踪,应该很容易弄清楚发生了什么。

3
从对代码的10秒快速查看,最有可能的原因是OnPropertyChanged。
从命名推测,它会引发一个事件。我们能看到这个方法的代码吗?很可能在调用事件处理程序之前没有进行空检查以检查是否有人已经订阅了。
[编辑-抱歉,没有读到您已确定isLoggedInLock是罪魁祸首]
您确定它是isLoggedInLock吗?因为这似乎没有太多的空间可以为空。由于它被标记为只读,它不可能在该方法的其他地方被设置为null。
这是否是受影响的代码的准确表示?属性绝对不是静态的,或者有某些差异吗?

2

您是否有静态构造函数?(并且它是否使用了IsLoggedIn?)


2

即使在构造函数中初始化了类的字段,当这个类通过反序列化进入生命周期时,该字段仍可能为空,因为构造函数不会被调用。


0

有可能将“isLoggedInLock”反射设置为null吗?使用FieldInfo.SetValue()可以更改只读字段的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接