Какова была бы лучшая практика для использования операторов switch? вложенный? конкретный? - PullRequest
3 голосов
/ 25 мая 2011

просто интересно, какой подход будет лучше, если оба блока кода дадут одинаковый результат:


string  from = ddFrom.SelectedItem.ToString(),
            to = ddTo.SelectedItem.ToString();

switch(from)
{
    case "celsius":
        switch(to)
        {
            case "celsius":
                break;
            case "fahrenheit":
                break;
            case "kelvin":
                break;
        }
        break;

    case "fahrenheit":
        switch(to)
        {
            case "celsius":
                break;
            case "fahrenheit":
                break;
            case "kelvin":
                break;
        }
        break;

    case "kelvin":
        switch(to)
        {
            case "celsius":
                break;
            case "fahrenheit":
                break;
            case "kelvin":
                break;
        }
        break;
}

или этот:


string  from = ddFrom.SelectedItem.ToString(),
            to = ddTo.SelectedItem.ToString(),
            conversion = from + to;

switch(conversion)
{
    case "celsiusfahrenheit":
        break;
    case "celsiuskelvin":
        break;
    case "fahrenheitcelsius":
        break;
    case "fahrenheitkelvin":
        break;
    case "kelvincelsius":
        break;
    case "kelvinfahrenheit":
        break;
}

Спасибо.

Ответы [ 5 ]

11 голосов
/ 25 мая 2011

Второй вариант предпочтительнее, потому что, как все уже говорили, он заставляет код выглядеть и чувствовать себя лучше.

Однако вы можете рассмотреть более архитектурный вариант:

public class TemperatureConverter
{
    private static readonly IDictionary<Tuple<string, string>, Func<double, double>> ConverterMap =
        new Dictionary<Tuple<string, string>, Func<double, double>>
        {
            { Tuple.Create("celsius", "kelvin"), t => t + 273 },
            // add similar lines to convert from/to other measurements
        }

    public static double Convert(double degrees, string fromType, string toType)
    {
        fromType = fromType.ToLowerInvariant();
        toType = toType.ToLowerInvariant();
        if (fromType == toType) {
            return degrees; // no conversion necessary
        }

        return ConverterMap[Tuple.Create(fromType, toType)](degrees);
    }
}

Использование:

TemperatureConverter.Convert(0, "celcius", "kelvin");

Конечно, это можно еще улучшить (прежде всего на ум приходит использование значений перечисления вместо строк для типов температуры, также необходима некоторая проверка ошибок), но общая идея есть.

ИМХО, это хороший промежуточный подход между мега- switch в старом школьном стиле и полноценным ОО-подходом (здесь нет реальной необходимости в ОО, поскольку у этой конкретной проблемы преобразования очень простая модель предметной области).

1 голос
/ 25 мая 2011

Лучше реструктурировать ваш код, чтобы у вас были классы шкалы температур и абстрактная фабрика, которая возвращает соответствующий экземпляр на основе входной строки:

public interface ITemperatureScale
{
    double GetAbsoluteValue();
    ITemperatureScale ConvertTo(ITemperatureScale temperatureScale);
}

public class CelciusScale : ITemperatureScale
{
    public double GetAbsoluteValue()
    {
        throw new NotImplementedException();
    }

    public ITemperatureScale ConvertTo(ITemperatureScale temperatureScale)
    {
        throw new NotImplementedException();
    }
}

public class FarScale : ITemperatureScale
{
    public double GetAbsoluteValue()
    {
        throw new NotImplementedException();
    }

    public ITemperatureScale ConvertTo(ITemperatureScale temperatureScale)
    {
        throw new NotImplementedException();
    }
}

public class KelvinScale: ITemperatureScale
{
    public double GetAbsoluteValue()
    {
        throw new NotImplementedException();
    }

    public ITemperatureScale ConvertTo(ITemperatureScale temperatureScale)
    {
        throw new NotImplementedException();
    }
}

public static class TemperatureScaleProvider
{
    private const string SCALE_CELSIUS = "celsius";
    private const string SCALE_KELVIN = "kelvin";
    private const string SCALE_FAHRENHEIT = "fahrenheit";

    public static ITemperatureScale GetFromString(string temperatureScaleString)
    {
        //Some input checks here
        switch (temperatureScaleString.ToLowerInvariant())
        {
            case (SCALE_CELSIUS):
                return new CelciusScale();
            case (SCALE_KELVIN):
                return new KelvinScale();
            case (SCALE_FAHRENHEIT):
                return new FarScale();
            default:
                throw new ArgumentException("temperatureScaleString");
        }

    }
}

Использование будет:

        ITemperatureScale fromScale = TemperatureScaleProvider.GetFromString("celcius");
        ITemperatureScale toScale = TemperatureScaleProvider.GetFromString("KELvIN");
1 голос
/ 25 мая 2011

Второй вариант будет лучше для быстрого результата и меньшего количества кода, поскольку он дает тот же результат.

0 голосов
/ 25 мая 2011

вариант # 2 выглядит чище и даст тот же результат

0 голосов
/ 25 мая 2011

Я думаю, что второй лучше, прямолинейнее и более читабелен. Второй подход будет легче поддерживать, модифицировать и расширять в будущем, если потребуется.

...