Альтернатива написанию многих операторов if? - PullRequest
1 голос
/ 20 декабря 2009

Вот мой метод:

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

Я хочу, чтобы метод получал выбранные из комбинированных списков и проверял значения. Но я хочу знать, есть ли альтернатива этому:

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

Кстати, я делаю своего рода конвертер единиц, поэтому у меня будут секции, отличные от углов. Поэтому я хотел бы иметь некоторые enum, interface, abstract class или class, которые я могу реализовать. Может быть, класс с именем Unit? Поэтому я могу создавать новые объекты, такие как Unit degrees = new Unit(Units.Angle), с единицами измерения в качестве перечисления. Или просто Unit sqrMillimeters = new Unit("Area");?

Ответы [ 5 ]

9 голосов
/ 20 декабря 2009

Конечно, полиморфизм. Каждый раз, когда вы видите длинные операторы switch или конструкции if / then / else, всегда можно обработать их, используя полиморфизм и фабрики. В вашем случае я бы предположил, что интерфейс ITemperaConConterter с конкретными реализациями для Фаренгейта, Селсиуса, Кельвина и Ранкина подойдет.

ОБНОВЛЕНИЕ:

Если вы обнаружите, что повторяете эту логику, почему бы не получить лучшую абстракцию для угла, чем для двойного?

Если вы пишете на объектно-ориентированном языке, неплохо подняться над примитивами (например, double и, yes, string), чтобы инкапсулировать поведение в объекты.

Я бы подумал о классе Angle, который будет зависеть от значения и возвращать его как любую меру, которую вы захотите.

Вот один из способов сделать это на Java. Я оставлю перевод на C #, а остальное для вас.

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);
    }
}
2 голосов
/ 20 декабря 2009

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

тогда

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

и dest = src*ratio

Таким образом, вместо N ^ 2 операторов if () у вас есть только N.

1 голос
/ 20 декабря 2009

Как насчет комбинации событий SelectedIndexChanged / SelectedValueChanged и некоторого полиморфизма?

1 голос
/ 20 декабря 2009

Можно ли как-нибудь написать вместо этого оператор switch?

switch (something)
{
  case "degrees" : do work
  ...etc
}
0 голосов
/ 20 декабря 2009

Вы можете объединить обе строки ("DegreesRadians") и вызвать метод с именем "DegreesRadians" через Reflection:

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

Где methodName - это объединенные строки (возможно, с дополнительной информацией, например, "convert" + unit1 + "2" + unit2, например "convertDegrees2Radians"), а параметры - это массив, содержащий оба значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...