itamar reif
itamar reif

Reputation: 149

Making a property only set-able by a specific method

I'm trying to make a chemistry equation balancer thingy. For that I made a class Element:

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

*elemEnum is an Enum of all the chemical elements.

I wanted to make the set for ElemType parse a string to the enumeration, but since set can only take in values of the same type as value I decided to add a method:

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

Is there an option to have the ElemType property be only set-able by the SetElemType method without having to make it private and adding a GetElemType method?

Upvotes: 4

Views: 1524

Answers (3)

Fabjan
Fabjan

Reputation: 13676

As already was pointed, you can use private setter, alternatively you can use readonly property with public getter that works with field and method to modify this field :

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
}

While it is practically the same as property with private setter it uses a slightly different approach...

Well if you really want to allow only one(!) method to change value you can use reflection and add class that envelopes your enum :

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
}

Upvotes: 0

Rotem
Rotem

Reputation: 21917

Since the most obvious solution from the comments has not been written as an answer:

Use a 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);
    }
}

This way, ElemType can only be set from within your own class.

Upvotes: 1

Kapol
Kapol

Reputation: 6463

without having to make it private

Well, you could create a workaround solution by adding a bool field to your class and modifying the property a little bit.

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;
    }
}

This solution may confuse the developer using your class, because setting the property will have no effect. It is much better to use a private setter for your task, as stated by others. I just wanted to show an alternative approach.

Upvotes: 0

Related Questions