【问题标题】:How to make a property set once and cannot be changed?如何使属性设置一次并且不能更改?
【发布时间】:2014-07-17 08:39:36
【问题描述】:

我有一个 Message 类,它具有三个属性 Content、Type 和 UniqueId。创建 Message 对象时,Content 和 Type 是已知的,因此我可以将它们传递给类的构造函数,并将 Content 和 Type 属性设置为只读,这样它们的值就不能再更改了。但是,对于 UniqueId,我需要在创建对象后在我的代码中计算它,并将值赋给 UniqueId 属性。由于我无法将 UniqueId 传递给构造函数并使该属性只读,我想知道是否有这样一种方法,一旦设置了属性 UniqueId,它的值就不能再更改了?

public class Message
{
    private readonly string content;
    private readonly AuditMessageType type;
    private Guid messageUId;

    public Message(string syslogMessage, AuditMessageType messageType, Guid messageUniqueId = new Guid())
    {
        content = syslogMessage;
        type = messageType;
        messageUId = messageUniqueId;
    }

    public string Message
    {
        get { return message; }
    }

    public AuditMessageType Type
    {
        get { return type; }
    }

    public Guid MesageUniqueId
    {
        get { return messageUId; }
        set { messageUId = value; } // How to make UniqueId property set once here? It cannot be pass in the constructor, as it needs to computed in the code after the object has been created. 
    }
}

【问题讨论】:

  • 这是我在c#中真正怀念的东西

标签: c# properties constructor


【解决方案1】:

你不能简单地创建一个保护标志吗?

bool wasSetMessageId = false;
public Guid MesageUniqueId
{
    get { return messageUId; }
    set 
    {
       if (!wasSetMessageId) 
       {
          messageUId = value;
          wasSetMessageId = true;
       } 
       else
       {
          throw new InvalidOperationException("Message id can be assigned only once");
       }
    } 
}

【讨论】:

  • @Yuval Itzchakov 为什么?我认为在 set 中对无效值抛出异常是件好事。我同意在get 中抛出异常是不好的做法。
  • 谢谢。我在一个项目中使用它。一个缺点是,如果某些代码确实尝试设置两次,错误不会在编译时发现,而是在运行时发现。
【解决方案2】:

方法:

如果Guid.EmptyMessageUniqueId的无效状态

  public Guid MesageUniqueId
    {
        get { return messageUId; }
        set {
             if (messageUId  == Guid.Empty) 
                messageUId = value; 
        } 
    }

如果您可以使用Nullable Guid 代替Guid

 public Guid ? MesageUniqueId
        {
            get { return messageUId; }
            set {
                 if (messageUId  == null) 
                    messageUId = value; 
            } 
        }

如果以上都做不到,请使用私有变量:

  private bool messageUniqueIdhasBeenSet = false ; 
 public Guid  MesageUniqueId
        {
            get { return messageUId; }
            set {
                 if (!messageUniqueIdhasBeenSet ) 
                  {
                    messageUId = value;
                    messageUniqueIdhasBeenSet = true ; 
                   } 
            } 
        }

【讨论】:

    【解决方案3】:
    private bool idHasBeenSet = false;
    public Guid MessageUniqueId
    {
        get { return messageUId; }
        set {
            if (idHasBeenSet) return; //or throw an exception if you need to
            messageUId = value;
            idHasBeenSet = true;
        }
    }
    

    【讨论】:

      【解决方案4】:

      c# 中没有这样的直接功能,但您可以自己编写代码,如下所示:-

      private Guid? messageUId;
       public Guid MesageUniqueId
          {
              get { return messageUId; }
              set {   
                    if (null == messageUId ) 
                    { 
                         messageUId = value;              
                    }
                    else  
                    { 
                        throw new InvalidOperationException("Message id can be assigned only once");
                    }
           }
          }
      

      【讨论】:

      • 错误 :) MessageUniqueId 属性不应为空。在这种情况下,您应该将字段 messageUId 设为可为空。
      猜你喜欢
      • 1970-01-01
      • 2016-12-04
      • 1970-01-01
      • 1970-01-01
      • 2013-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多