【问题标题】:How does SET works with property in C#?SET 如何处理 C# 中的属性?
【发布时间】:2010-05-10 21:37:29
【问题描述】:

我想知道 set 在属性中的作用不仅仅是设置私有成员变量的值。假设我的班级中有一个私人成员 (private int myInt)。

例如,我可以确保返回的值不是负数

get
{
  if(myInt < 0)
    myInt = 0;
  return myInt;
}

使用 SET,我所能做的就是像这样影响私有变量

set { myInt = value; }

我没有在任何一本书中看到我能做的更多。如果我不想在影响 myInt 的值之前做一些操作呢?假设:如果值为负,则影响 0 到 myInt。

set
{
  //Check if the value is non-negative, otherwise affect the 0 to myInt
}

感谢您的帮助

【问题讨论】:

    标签: c#


    【解决方案1】:

    你可以为所欲为。

    没有什么可以阻止你拥有:

    set
    {
        if (value < 0)
            myInt = 0;
        else
            myInt = value;
    }
    

    (或更紧凑的版本)

    这就是 setter 和 getter 的设计目的。

    如果值超出范围,您可以添加日志记录、调试断言甚至引发异常。

    但是

    您的 Setter 和 Getter 的用户不会期望他们进行“大量”处理或产生任何副作用。所以他们应该只影响他们的支持变量,而不是去处理 1000 个文本文件(例如)。与数据库的连接很好,但如果您要返回大量数据,则应将 Get 替换为显式函数。

    另外,请注意@StingyJack 在他的回答中所说的话。

    【讨论】:

      【解决方案2】:

      你可以在一个“集合”中做任何事情。你问的具体例子:

      set { 
        // Silently set to a more correct value
        myInt = value < 0 ? 0 : value; 
      }
      

      set { 
        // Always return error to caller
        if (value < 0) {
           throw new ArgumentException("value", "value cannot be negative.")
        }
        myInt = value; 
      }
      

      set { 
        // When debugging, warn the developer, in release adjust value silently
        Debug.Assert(value >= 0, "Value should 0 or larger");
        myInt = value < 0 ? 0 : value; 
      }
      

      【讨论】:

        【解决方案3】:

        属性编译为常规方法,因此您可以在 set 语句中执行任何操作。理论上,您甚至不需要访问单个成员变量或使用 value 关键字。尽管如此,使用 setter 来做的不仅仅是设置成员变量,这通常被认为是一种不好的做法。

        【讨论】:

          【解决方案4】:

          你可以这样做:

          set { myInt = value < 0 ? 0 : value; }
          

          无论你想要什么逻辑,你都可以使用value,就像任何其他Int...或者你的属性是什么类型,value就是那种类型,你可以用它做你想做的事: )

          【讨论】:

            【解决方案5】:

            我能想到几个原因 - setter 简单得多,但 setter 在更复杂的情况下可能非常有用:

            底层存储类型与暴露类型不同

            当您围绕其他对象创建包装器并希望隐藏复杂性时,可能会出现这种情况

            有时转换可能很简单(double 到 int 等...),有时它可能更复杂(Xml 到一些强类型对象)。

            class ThingWrapper
            {
                public Thing Thing {get; set;}
            
                public int SomeProperty
                {
                    get
                    {
                        return int.Parse(this.Thing.SomeProperty);
                    }
                    set
                    {
                        Thing.SomeProperty = value.ToString();
                    }
                }
            }
            

            你想阻止一个属性改变

            也许您有某种对象暴露了在另一个线程中运行的长时间运行的后台任务,并且您希望防止用户在该任务运行时更改属性。

            你需要脱离事件

            您可能有一些对象公开了您订阅的事件,并且您还希望能够设置该对象(出于某种原因)。在这种情况下,您需要确保将事件处理程序与旧对象分离并重新附加到新对象。

            【讨论】:

              【解决方案6】:

              这样的属性:

              public int SomeValue
              {
                  get { return _SomeValue; }
                  set { _SomeValue = this; }
              }
              

              基本上是这样的:

              public int SomeValue { get; set; }
              
              public int get_SomeValue()
              {
                  return _SomeValue;
              }
              
              public void set_SomeValue(int value)
              {
                  _SomeValue = value;
              }
              

              所以你可以放入两个类似的方法中的任何东西对于两个属性访问器方法都是有效的。

              【讨论】:

                【解决方案7】:

                就像所有这些答案所说的那样,你可以在一个系列中做任何你想做的事情。这并不意味着你应该……

                举一个有点做作的例子

                Public Class MyClass
                
                 Private m_myValue as String
                
                 Public Property MyValue as String
                  Get
                   If String.IsNullOrEmpty(m_myValue) Then
                    Return String.Empty
                   Else
                    Return m_myValue
                   End If
                  End Get
                  Set (Value as String)
                   If String.IsNull(m_myValue) = False Then
                    m_myValue = Value
                   End If
                  End Set
                 End Property
                
                 Public Function GetLengthOfMyValue() as Integer
                  Return m_myValue.Length
                 End Function
                
                End Class
                

                如果您要运行以下 sn-p,_len2 调用会给您一个异常,因为它没有扩展属性提供的相同空值保护。

                Dim _mc as New MyClass()
                Dim _len1 as Integer = _mc.MyValue.Length
                Dim _len2 as Integer = _mc.GetLengthOfMyValue()
                

                现在,就像我说的那样,这是一个人为的例子,但我确实看到它在实践中经常发生,并且在许多情况下,它会增加可能导致错误或其他意外后果的细微行为差异。

                • 函数应该使用属性吗?您的偏好是什么(您的组织的编码标准是否已经为您决定)?
                • 有没有更好的方法可以在不重复代码的情况下完成您的任务?

                在使用此模式之前,您可能需要考虑一下。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-09-15
                  • 2010-10-25
                  • 1970-01-01
                  • 2019-08-17
                  • 1970-01-01
                  • 2016-02-11
                  • 1970-01-01
                  相关资源
                  最近更新 更多