当给属性设置值时出现NullReferenceException异常

4
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    class Cls : INotifyPropertyChanged
    {
        private string my;
        public  string MyProperty
        {
            get
            {
                return my;
            }
            set
            {
                my = value;
                PropertyChanged(this, new PropertyChangedEventArgs("MyProperty")); 
            }

        }

        public Cls()
        {
            MyProperty = "Hello";
        }

        public void print()
        {
            Console.WriteLine(MyProperty);
        }

        protected virtual void OnPropertyChanged(string name)
        {
        }

        public event PropertyChangedEventHandler PropertyChanged;

    }

    class Program
    {
        static void Main(string[] args)
        {
            Cls s = new Cls();
            s.print();
        }
    }
}

当我运行这段代码时,它会显示:
未经处理的异常: System.NullReferenceException: 对象引用未设置到对象的实例。
当我不使用INotifyPropertyChanged时,它能够正常工作。我不理解问题的原因。

2
哪一行导致了错误? - Kuzgun
MyProperty = "Hello"; - Pranit Kothari
4个回答

21

没有任何人监听 PropertyChanged,因此在尝试调用它时将为空。请改用 OnPropertyChanged 方法:

private void OnPropertyChanged(string propertyName){
    var handler = PropertyChanged;
    if (handler != null)
        handler(this, new PropertyChangedEventArgs(propertyName));

    // With C# 6 this can be replaced with
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public  string MyProperty
{
    get { return my; }
    set
    {
       if (my == value)
           return;

        my = value;
        OnPropertyChanged("MyProperty");
    }
}

为了避免它为null,您需要订阅它,例如从您的主方法中:
static void Main(string[] args){
    Cls s = new Cls();
    s.PropertyChanged += (sender, args) => MessageBox.Show("MyProperty changed!");
    s.print();
}

这是一种花哨的写法,涉及到IT技术。
static void Main(string[] args){
    Cls s = new Cls();
    s.PropertyChanged += ShowMessage;
    s.print();
}

private void ShowMessage(object sender, PropertyChangedEventArgs args){
    MessageBox.Show("MyProperty changed!");
}

无论对您来说更清晰的是什么。
您可以在此处阅读有关事件的更多信息


6
如果没有任何东西订阅 PropertyChanged 事件,触发此事件将抛出 NullReferenceException。在触发事件之前,您需要进行空值检查,像这样:
if (PropertyChanged != null)
{
    PropertyChanged(this, new PropertyChangedEventArgs("MyProperty"));
}

运行良好。但是什么使PropertyChanged非空..意味着它最初如何为空,之后又变为非空。 - Pranit Kothari

4

PropertyChanged委托没有侦听器。在引发它之前,您应该始终检查委托是否为null。

if (PropertyChanged != null)
{
    PropertyChanged(this, new PropertyChangedEventArgs("MyProperty"));
}

此外,从你的代码来看,你可能希望在属性变化时调用 OnPropertyChanged。为了实现这一点,你应该向PropertyChanged添加事件监听器,并在监听器中调用 OnPropertyChanged。可以通过添加以下代码来实现:
//Old ctor
public Cls()
{
    PropertyChanged += new PropertyChangedEventHandler(Cls_PropertyChanged); //Register the event handler
    MyProperty = "Hello";
}

void Cls_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    OnPropertyChanged(e.PropertyName); //Call your method
}

0
我在我的“视图模型”类中收到了错误,因为我省略了INotifyPropertyChanged接口声明。
所以从像这样的东西开始。
public class viewmodel
   {}

转换成这个

public class viewmodel: INotifyPropertyChanged
 {}

已修复。


这对楼主没有帮助,但是其他人可能会犯同样的错误吗?


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