【问题标题】:Why does the SetProperty() method of INotifyPropertyChanged need a ref argument?为什么 INotifyPropertyChanged 的​​ SetProperty() 方法需要一个 ref 参数?
【发布时间】:2019-05-14 16:38:55
【问题描述】:

考虑到 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));
    }

为什么SetPropertymethod 需要一个 ref 参数?除了类字段之外几乎没有任何机会传递给方法,所以它应该始终是引用类型?

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

【问题讨论】:

  • 阅读ref 关键字的文档。它会告诉你它的确切作用......
  • 谢谢,虽然我知道 ref 关键字的作用,但我的问题是为什么在这种特殊情况下需要它。
  • 如果您知道 ref 关键字的作用,那么您也知道 SetProperty 的作用(即为什么 SetProperty 使用 ref 关键字)。为什么需要问? o.O?
  • SetPropertystorage 所做的唯一事情是设置storage = value。如果storage 没有通过引用传递,那行代码将什么都不做。 If 会在方法内本地更新该变量,但这并不重要,因为在那之后该变量就不再使用了。
  • 它将是一个引用,按值传递。这与通过引用传递的变量不同。有关详细信息,请参阅jonskeet.uk/csharp/parameters.html

标签: c# inotifypropertychanged ref


【解决方案1】:

目的是您通过引用传递一个字段,以及新值。

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

storage = value;

... 毫无意义。这会改变 参数 的值,但根本不会修改 字段

这里有一个完整的例子来说明区别:

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 做了。

【讨论】:

  • 感谢您的回答和示例!
猜你喜欢
  • 2011-02-21
  • 2015-01-02
  • 2013-07-08
  • 1970-01-01
  • 2020-09-02
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 2013-10-22
相关资源
最近更新 更多