将值设置为属性时的NullReferenceException

时间:2014-02-17 16:03:07

标签: c# .net exception inotifypropertychanged

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时,它可以正常工作。我不明白问题的原因。

4 个答案:

答案 0 :(得分:20)

没有人听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,您必须订阅它,例如从您的main方法订阅:

static void Main(string[] args){
    Cls s = new Cls();
    s.PropertyChanged += (sender, args) => MessageBox.Show("MyProperty changed!");
    s.print();
}

这是一种奇特的写作方式

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

对你来说更清楚的是什么 您可以阅读有关事件here

的更多信息

答案 1 :(得分:5)

如果没有订阅PropertyChanged事件,则触发该事件将抛出NullReferenceException。您需要在触发事件之前进行空检查,如下所示:

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

答案 2 :(得分:4)

PropertyChanged委托没有监听器。在引发委托之前,应始终检查委托是否为空。

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
}

答案 3 :(得分:0)

我在我的“视图模式”中收到了错误消息。 class因为我省略了INotifyPropertyChanged接口声明。

所以从这样的事情

<%= javascript_include_tag('test.js') %>

到这个

public class viewmodel
   {}

修好了。

不会对OP有所帮助,但是对其他人可能会做出疏忽吗?

相关问题