开发者

Alternative to writing many if statements?

开发者 https://www.devze.com 2022-12-14 16:51 出处:网络
Here is my method: private void ConvertValues() { txtResult.Text = angles[cmbUnits1.SelectedIndex]; double value1 = Convert.ToDouble(txtValue1.Text);

Here is my method:

private void ConvertValues()  
{  
    txtResult.Text = angles[cmbUnits1.SelectedIndex];  
    double value1 = Convert.ToDouble(txtValue1.Text);  
    double value2 = Convert.ToDouble(txtValue2.Text);  
    int unit1 = cmbUnits1.SelectedIndex;  
}

What I want the method to do is to get the selected of the ComboBoxes and test the 开发者_如何转开发values. But I want to know if there is an alternative to this:

if( angles[cmbUnits1.SelectedIndex].Equals("Degrees") && 
    angles[cmbUnits2.SelectedIndex].Equals("Radians")) {  
    ...  
}

By the way, I'm making a kind of unit converter so I will have sections other than angles. So I would like some enum, interface, abstract class, or class that I can implement. Maybe a class with the name Unit? So I can create new objects like Unit degrees = new Unit(Units.Angle) with Units as an enum. Or just Unit sqrMillimeters = new Unit("Area");?


Sure, polymorphism. Anytime you see long switch statements or if/then/else constructs it's always possible to handle them using polymorphism and factories. In your case I'd imagine an ITemperatureConverter interface with concrete implementations for Fahrenheit, Celcius, Kelvin, and Rankine would do nicely.

UPDATE:

If you find you have this logic repeated, why not have a better abstraction for an Angle than a double?

If you're writing in an object-oriented language, it's a good idea to rise above primitives (e.g, double and, yes, string) to encapsulate behavior into objects.

I'd think about an Angle class that would hang onto the value and return it as whatever measure you wanted.

Here's one way to do it in Java. I'll leave the translation to C# and the rest for you.

package angles;

public class Angle
{
    private double value;
    private AngleUnit units;

    public Angle()
    {
        this(0.0, AngleUnit.RADIANS);
    }

    public Angle(double value)
    {
        this(value, AngleUnit.RADIANS);
    }

    public Angle(double value, AngleUnit units)
    {
        this.value = value;
        this.units = units;
    }

    public double getValue()
    {
        return value;
    }

    public AngleUnit getUnits()
    {
        return units;
    }

    public Angle convert(AngleUnit newUnits)
    {
        Angle newAngle = null;

        if (this.units.equals(newUnits))
        {
            return this;
        }

        return newAngle;
    }
}

package angles;

public interface AngleConverter
{
    Angle convert(Angle angle, AngleUnit to);
}

package angles;

public enum AngleUnit
{
    DEGREES, RADIANS, GRADIANS;
}

package angles;

import java.util.HashMap;
import java.util.Map;

public class DegreeConverter implements AngleConverter
{
    private final Map<AngleUnit, Double> factors;

    public DegreeConverter(Map<AngleUnit, Double> factors)
    {
        this.factors = new HashMap<AngleUnit, Double>();
        this.factors.put(AngleUnit.DEGREES, 1.0);
        this.factors.put(AngleUnit.RADIANS, Math.PI/180.0);
        this.factors.put(AngleUnit.GRADIANS, 100.0/90.);
    }

    public Angle convert(Angle angle, AngleUnit to)
    {
        assert angle != null && to != null;

        return new Angle(angle.getValue()*this.factors.get(to), to);
    }
}


double UnitToFactor(string unit) { returns 1 for radians, pi/180 for degrees, etc }

then

ratio = UnitToFactor(unit1) / UnitToFactor(unit2);

and dest = src*ratio

This way, instead of N^2 if() statements, u have only N.


Is there any way you could write a switch statement instead?

switch (something)
{
  case "degrees" : do work
  ...etc
}


How about a combination of SelectedIndexChanged / SelectedValueChanged Events and some polymorphism ?


You could concatenate both strings ("DegreesRadians") and call a Method called "DegreesRadians" via Reflection:

MethodInfo theMethod = thisType.GetMethod(methodName);
theMethod.Invoke(this, parameters);

Where methodName are the concatenated strings (maybe with additional information, like "convert" + unit1 + "2" + unit2, like "convertDegrees2Radians"), and parameters is an array containing both values.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号