分配相同值时未调用c#property setter

时间:2014-05-23 11:59:25

标签: c# properties setter

我有一个像这样定义的属性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#这样做了,在我的所有安装程序中我都有这样的代码: if(value!= _myValue){do setter logic here} 我想我不需要写那个支票了吗?

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

感谢

3 个答案:

答案 0 :(得分:17)

对于它的价值 - 我遇到了这个问题,在我们的代码库中它已经达到了Fody

Fody插入相等检查并使设定器短路。我并没有真正期待你的问题归结为Fody(因为你提到了视觉设计师)。我认为对我这样做的人来说,这可能是有价值的。

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

为了您的利益,我使用dotPeek检查winforms PropertyGrid并找到下面的代码片段。视觉工作室可能会有所不同,但我强烈怀疑它正在做类似的事情。如果您非常热衷于在设置不同值时可以记录调用堆栈。调用堆栈中的某个位置是具有相等性检查的函数。

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]禁用它。

答案 1 :(得分:3)

问题在于视觉工作室的有缺陷的设计师。 在设计时使用“属性窗口”设置属性值时,如果属性值已经存在,则此窗口不会设置该属性的值。

在代码中执行此操作时没有任何问题,无论如何都将设置该值。

这是微软试图帮助你的另一个很好的例子(所有这些都可以帮助你倒退而不是前锋......)

答案 2 :(得分:0)

我今天在properyGrid中使用文件名属性遇到了同样的问题。 我发现一个简单的变通办法是零星的,但这对我有好处。我没有在getter中返回_ggFileName,而是返回了“浏览文件” 我确保不使用吸气剂,而是使用字段

因此,基本上唯一使用吸气剂的是属性网格,这当然不是很好的编程方法,但是它很快就为我解决了这个问题。

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