c#属性设置器在赋值相同时未被调用

本文关键字:调用 赋值 属性 设置 | 更新日期: 2023-09-27 18:05:01

我有一个像这样定义的属性ggFileName:

    private string _ggFileName = "";
    public string ggFileName
    {
        get 
        { 
            return _ggFileName;
        }
        set 
        {
            _ggFileName = value;
            ReadXmlSchemaFromFile();
        }
    }

当赋值给ggFileName时,方法ReadXmlSchemaFromFile();被称为。到目前为止一切顺利。

我的问题是,当我用它已经包含的相同值分配属性ggFileName时,什么也不会发生。除非给setter赋一个不同的值,否则它不会被调用。

我同意在几乎所有情况下这都是完全合乎逻辑的,但在我的情况下,它提出了一个问题。如果ggFileName中的文件在我的应用程序之外被更改了怎么办?将相同的文件再次分配给ggFileName不会调用我的setter,因此也不会调用ReadXmlSchemaFromFile()。所以现在我必须将虚拟文件设置为属性ggFileName,然后再次将相同的文件分配给ggFileName以使其工作。

c#似乎想要通过在分配相同值时不调用setter来帮助我,我如何告诉c#停止帮助我?

我不知道c#会这样做,在我所有的setter中,我有这样的代码:if (value != _myValue){在这里做setter逻辑}我想我再也不需要写那张支票了。

为了让事情更清楚,因为人们似乎不理解我的问题。1. 我的setter确实会被调用,但只有在赋值不同时才会被调用2. 我不想使用方法,因为在设置属性之后,我希望完成一些检查,并且我不希望类的任何其他用户能够绕过该检查。这就是属性的作用,还是不是?3.赋值的代码不能发布。它是自定义控件的属性,设计人员可以通过编辑对象检查器来调用它。同样,只要输入不同的值

它就能工作

谢谢

c#属性设置器在赋值相同时未被调用

为了它的价值-我遇到了这个问题,在我们的代码库中,它被归结为Fody。

Fody插入一个相等校验并使setter短路。我并不认为你的问题是Fody造成的(因为你提到了视觉设计师)。我想它可能会对其他像我一样看到这篇文章的人有价值。

我使用dotPeek来查找正在插入的代码。

为了您的利益,我使用dotPeek检查winforms PropertyGrid并找到下面的代码片段。visual studio可能会有所不同,但我强烈怀疑它正在做类似的事情。如果你真的很喜欢,你可以在设置不同的值时记录调用堆栈。在调用堆栈的某个地方应该是具有相等性检查的函数。

private object SetPropertyValue(object obj, object objVal, bool reset, string undoText)
{
  DesignerTransaction designerTransaction = (DesignerTransaction) null;
  try
  {
    object propertyValueCore = this.GetPropertyValueCore(obj);
    if (objVal != null && objVal.Equals(propertyValueCore)) // if equal return!!!!
      return objVal;
    this.ClearCachedValues();
关于Fody

:

这种在新指令中"编织"的技术是不可思议的强大。您可以将简单的公共属性转换为完整的INotifyPropertyChanged实现,增加空参数检查;将Git哈希添加到你的程序集中,甚至创建所有的字符串比较不区分大小写。

值得注意的是,它可以被[DoNotCheckEquality]禁用。

问题出在visual studio的bug设计器上。当在设计时使用"属性窗口"设置属性值时,此窗口不会为您的属性设置与已经存在的值相同的值。

在代码中这样做是没有问题的,无论如何都会设置该值。

这是微软如何帮助你的又一个很好的例子(都是帮助你向后而不是向前…)

我今天在properyGrid中的一个文件名属性中遇到了同样的问题。我发现了一个简单的变通方法,虽然不完整,但对我来说很好。我没有在getter中返回_ggFileName,而是返回"Browse File"我没有使用getter而是使用了字段

所以基本上唯一使用getter的是属性网格,当然这不是很好的编程,但它很快为我解决了问题

private string _ggFileName = "";
public string ggFileName
{
    get 
    { 
        return "Browze File";
    }
    set 
    {
        _ggFileName = value;
        ReadXmlSchemaFromFile();
    }
}