Search code examples
c#classvariablescasting

Casting an object to its class


I am trying to create some classes with two variables. One of the variables is Name the other one is Value. For each class value can be different type of variables (int , double or string).

I want to store instances of these classes in a List so I placed the classes under an abstract class.

Then inside a foreach loop I want to use the Value of these instances but I need them casted into their original type so that the param.Set function will accept it.

My code is like this:

List<ElementProperty> parameters = new List<ElementProperty>();
//I add my parameters to the list.
parameters.Add(new ElementProperty.String("TestName", "TestVariable"));
parameters.Add(new ElementProperty.Integer("TestName", 10));

//I want to make this foreach loop shorter and more proper
foreach (var parameter in parameters)
{
    Parameter param = el.LookupParameter(parameter.Name);
    if (parameter is ElementProperty.Boolean)
    {
        param.Set(((ElementProperty.Boolean)parameter).Value);
        //param.Set only accepts int double and string
    }
    else if (parameter is ElementProperty.Double)
    {
        param.Set(((ElementProperty.Double)parameter).Value);
    }
    else if (parameter is ElementProperty.Integer)
    {
        param.Set(((ElementProperty.Integer)parameter).Value);
    }
    else if (parameter is ElementProperty.String)
    {
        param.Set(((ElementProperty.String)parameter).Value);
    }
}

public abstract class ElementProperty
{
    public string Name;
    public object Value;

    public class Integer : ElementProperty
    {
        public new int Value;
        public Integer(string Name, int Value)
        {
            this.Name = Name;
            this.Value = Value;
        }
    }

    public class Double : ElementProperty
    {
        public new double Value;
        public Double(string Name, double Value)
        {
            this.Name = Name;
            this.Value = Value;
        }
    }

    public class String : ElementProperty
    {
        public new string Value;
        public String(string Name, string Value)
        {
            this.Name = Name;
            this.Value = Value;
        }
    }

    public class Boolean : ElementProperty
    {
        public new int Value;
        public Boolean(string Name, bool Value)
        {
            this.Name = Name;

            if (Value is false)
            {
                this.Value = 0;
            }
            else
            {
                this.Value = 1;
            }
        }
    }
}

Is there a better option? Any suggestion would help a lot. Thank you.


Solution

  • I prefer using Interfaces for this, but you could do something like this:

    // ...
    foreach (var parameter in parameters)
    {
        parameter.SetTo(param); // Call same interface
    }
    // ...
    

    In each of those concrete classes:

    public class Integer : ElementProperty
    {
        public new int Value;
        public Integer(string Name, int Value)
        {
            this.Name = Name;
            this.Value = Value;
        }
        public void SetTo(Parameter p)
        {
             p.Set(this.Value); // calls correct overload
        }
    }
    

    This works completey without switch/case or if/else chains.

    However, be aware that the urge to use this pattern may be a hint to underlying design issues. Which is the reason it is sometimes perceived as a "code smell".