为什么INotifyPropertyChanged的SetProperty()方法需要ref参数?

时间:2019-05-14 16:38:55

标签: c# inotifypropertychanged ref

考虑实现INotifyPropertyChanged通常看起来像这样:

    public class Observable : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void SetProperty<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
        {
            if (Equals(storage, value))
            {
                return;
            }

            storage = value;
            OnPropertyChanged(propertyName);
        }

        protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

为什么SetProperty方法需要ref参数?除了类字段外,几乎没有任何其他机会传递给该方法,因此它始终应该始终是引用类型吗?

注意:我问这个问题是因为我想将此方法用于通过foreach循环枚举的项目,而该循环不适用于ref关键字。

1 个答案:

答案 0 :(得分:4)

目的是通过引用传递 field 以及新值。

如果这不是一个ref参数,那么您将传递字段的 ...此时,该语句:

storage = value;

...将毫无意义。那会改变参数的值,但根本不会修改 field

下面是一个完整的例子来说明区别:

using System;

class Program
{
    static string field;

    static void Main()
    {
        field = "initial value";
        Console.WriteLine($"Before Modify1: {field}");

        Modify1(field, "new value for Modify1");
        Console.WriteLine($"After Modify1: {field}");

        Modify2(ref field, "new value for Modify2");
        Console.WriteLine($"After Modify2: {field}");
    }

    static void Modify1(string storage, string value)
    {
        // This only changes the parameter
        storage = value; 
    }

    static void Modify2(ref string storage, string value)
    {
        // This changes the variable that's been passed by reference,
        // e.g. a field
        storage = value;
    }        
}

输出:

Before Modify1: initial value
After Modify1: initial value
After Modify2: new value for Modify2

如您所见,Modify1(没有ref)根本没有修改该字段,而Modify2却没有修改。