【问题标题】:Making a property only set-able by a specific method使属性只能通过特定方法设置
【发布时间】:2015-10-18 09:58:04
【问题描述】:

我正在尝试制作一个化学方程式平衡器。为此我制作了一个类元素:

class Element
{
    public elemEnum ElemType {get; set;}
    public double Amount {get; set;} // How many atoms of this type in the formula
}

*elemEnum 是所有化学元素的枚举。

我想让setElemType 解析一个字符串到枚举,但由于set 只能接受与value 相同类型的值,我决定添加一个方法:

public void SetElemType(string type)
{
    this.ElemType = (elemEnum)Enum.Parse(typeof(elemEnum), type);
}

是否可以选择让ElemType 属性只能通过SetElemType 方法设置,而不必使其成为private 并添加GetElemType 方法?

【问题讨论】:

  • C# 中有私有的 getter/setter。 public elemEnum ElemType { get; private set; }。你试过用那个吗?
  • 对于您的问题,我认为不可能使用自动 setter/getter 方法来接受与变量类型不同的类型。您可以将 ElemType 的 setter 设置为 private,以确保它只能在类中设置。也许是主题,但 C# 中的类型名称应该是帕斯卡大小写,意思是“elemEnum”应该是“ElemEnum”
  • 好吧,也许你能做到,这样的财产有什么目的?
  • 常见的解决方案是使用私有设置器,如 Caramiriel 的评论所示。您的属性可能仍由您班级的其他成员设置,但这应该不是问题,因为您可以完全控制班级的实施。
  • @EdoPost 我不知道有私有集/获取器。我对大写的不好,我对此有点陌生,我会在未来注意到它。

标签: c# properties enums


【解决方案1】:

由于 cmets 中最明显的解决方案尚未被写为答案:

使用private setter

class Element
{
    public ElemEnum ElemType {get; private set;}
    public double Amount {get; set;}

    public void SetElemType(string type)
    {
        this.ElemType = (ElemEnum)Enum.Parse(typeof(ElemEnum), type);
    }
}

这样,ElemType 只能在您自己的类中设置。

【讨论】:

  • 我不太确定将其设为私有 setter 是否是最佳解决方案,如果目标是制作只能通过该方法设置的专业人士,那么仅将其设为私有是行不通的它。因为该类中的任何方法都可以编辑该值。因此,我会说 Kapol 的答案是解决这个问题的更好方法。
  • @EdoPost 我怀疑 OP 是否试图保护它免受他自己类的方法,而不是外部操纵。
  • @EdoPost 是的,Rotem 是正确的。除了属性、构造函数和方法之外,该类可能甚至不会包含任何内容。
【解决方案2】:

无需将其设为私有

好吧,您可以通过将bool 字段添加到您的类并稍微修改属性来创建解决方案。

class Element
{
    private bool _elemCanBeSet = false;
    private elemNum _elemType;

    public elemEnum ElemType
    {
        get { return _elemType; }
        set { if (_elemCanBeSet) _elemType = value; }
    }

    public double Amount {get; set;} // How many atoms of this type in the formula

    public void SetElemType(string type)
    {
        _elemCanBeSet = true;
        this.ElemType = (elemEnum)Enum.Parse(typeof(elemEnum), type);
        _elemCanBeSet = false;
    }
}

此解决方案可能会使使用您的类的开发人员感到困惑,因为设置属性将无效。正如其他人所说,为您的任务使用私有设置器要好得多。我只是想展示另一种方法。

【讨论】:

  • 为什么你更喜欢它而不是现有的语言结构 - 私有设置器?
  • @Rotem OP 几乎要求避免现有的语言结构。我认为您的评论应该是对问题的评论,而不是对这个答案的评论。
  • @Rotem 我不喜欢它。我只是想展示如何在不将属性设为私有的情况下实现 OP 的目标(请参阅我帖子开头的引文)。
  • @hvd OP 询问他们如何避免将整个属性设为私有(因此必须提供额外的手动 getter 和 setter)。 OP 不知道私人二传手。
  • 大声笑,如果我们添加另一个方法,将_elemCanBeSet 更改为true,然后毫无问题地修改值呢?在这种情况下这有什么帮助?
【解决方案3】:

正如已经指出的,您可以使用private setter,或者您可以使用readonly 属性和public getter,它与字段和方法一起使用来修改此字段:

class Element
{
   private elemEnum _elemType;

   public elemEnum ElemType { get { return _elemType; } }

   public void SetElemType(string type) 
   {
      this._elemType = (elemEnum)Enum.Parse(typeof(elemEnum), type);
   }

   public double Amount {get; } // How many atoms of this type in the formula
}

虽然它实际上与 private setter 的属性相同,但它使用的方法略有不同...

如果你真的想只允许一个(!)方法来改变值,你可以使用反射并添加包含你的枚举的类:

class MyElemSetter
{
    private readonly elemEnum elem;

    public MyElemSetter(elemEnum e, Action helperAction)
    {
        MethodInfo callingMethodInfo = helperAction.Method;

        if (helperAction.Method.Name.Contains("<SetElemType>")) elem = e;
    }

    public static implicit operator elemEnum(MyElemSetter e)
    {
        return e.elem;
    }
}

class Element
{
    private MyElemSetter _elemType;

    public elemEnum ElemType { get { return _elemType; } }

    public void SetElemType(string type)
    {
        this._elemType = new MyElemSetter((elemEnum)Enum.Parse(typeof(elemEnum), type), () => { });
    }

    public double Amount { get; set; } // How many atoms of this type in the formula
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多