首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >硅单元变换器

硅单元变换器
EN

Code Review用户
提问于 2015-12-02 18:49:36
回答 2查看 3.3K关注 0票数 22

我最近开始了“编码”,这是我的第一个“项目”。它应该是一个SI转换器,在这里你可以键入一个值,它的单位和你想要它被转换到的单位。

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Program
{
    class Program
    {
        static void Main()
        {


            decimal one = 1;
            decimal two = 0.001m;
            decimal three = 0.000001m;
            decimal four = 0.000000001m;
            decimal five = 0.000000000001m;
            decimal answer;
            int y = 0;

            while (y < 1)
            {


                Console.WriteLine("SI converter!\nPlease, enter value: ");
                decimal value = Convert.ToInt32(Console.ReadLine());

                Console.WriteLine("\nFactors: \n1.One \n2.Milli(m)\n3.Micro(µ)\n4.Nano(n)\n5.Pico(p)\nEnter factor: ");
                decimal factor = int.Parse(Console.ReadLine());

                if (factor == 1)
                {
                    factor = one;
                }
                else if (factor == 2)
                {
                    factor = two;
                }
                else if (factor == 3)
                {
                    factor = three;
                }
                else if (factor == 4)
                {
                    factor = four;
                }
                else if (factor == 5)
                {
                    factor = five;
                }


                Console.WriteLine("\nFactors: \n1.One \n2.Milli(m)\n3.Micro(µ)\n4.Nano(n)\n5.Pico(p)\nEnter the second factor: ");
                decimal factor2 = Convert.ToInt32(Console.ReadLine());

                if (factor2 == 1)
                {
                    factor2 = one;
                    answer = value * factor;
                    Console.WriteLine("The answer is : " + answer);
                }
                else if (factor2 == 2)
                {
                    factor2 = two;
                }
                else if (factor2 == 3)
                {
                    factor2 = three;
                }
                else if (factor2 == 4)
                {
                    factor2 = four;
                }
                else if (factor2 == 5)
                {
                    factor2 = five;
                }



                answer = value * factor / factor2;
                Console.WriteLine("The answer is : " + answer);


                Console.WriteLine("Go again?\nY / N");
                char ans = char.Parse(Console.ReadLine());
                if (ans == 'n')
                {
                    y = 8;
                }
                if (ans == 'y')
                {

                    y = 0;
                    Console.Clear();

                }
            }
        }
    }
}
    }

你能给我一些关于代码和我如何改进的意见吗?

EN

回答 2

Code Review用户

发布于 2015-12-02 18:59:35

我只是想让你的元素名和SI因子一致,比如

代码语言:javascript
复制
        decimal unit = 1;
        decimal milli = 0.001m;
        decimal micro = 0.000001m;
        decimal nano = 0.000000001m;
        decimal pico = 0.000000000001m;

甚至还有更像

代码语言:javascript
复制
        decimal kilo = 1000.0;
        decimal mega = 1000000.0;
        decimal deci = 0.1m;
        decimal centi = 0.01m;

这将使代码的意图在有如下语句时更加可读性和简洁性:

代码语言:javascript
复制
if (factor == 1) {
    factor = unit;
}

此外,我还会将用户的选择和选择的因素分离到不同的变量中,例如:

代码语言:javascript
复制
            int choice = Convert.ToInt32(Console.ReadLine());

            switch(choice) {
            case 1:
                factor = unit;
                break;
            case 2:
                factor = milli;
                break;
            // etc.
            }

明确区分用户输入和实际选择的因素。这将使代码更加可读性、可维护性和简洁性。

此外,由于您一直专门要求c#,所以可以直接将用户输入作为字符串,而不需要从数字映射:

代码语言:javascript
复制
Console.WriteLine("\nFactors: \nUnit \nMilli(m)\nMicro(µ)\nNano(n)\nPico(p)\nEnter factor: ");
string choice = Console.ReadLine();

switch(choice) {
case "Unit":
    factor = unit;
    break;
case "Milli":
    factor = milli;
    break;
// etc.
}

或者从正确初始化的Dictonary<string, double>中查找因子值。

票数 16
EN

Code Review用户

发布于 2015-12-02 20:12:17

这将是一个更长的例子,我只是在这里处理转换逻辑,因为我认为这是最有教育意义的。这也不是一个“真实世界”的例子,因为你提供的具体案例并不能证明任何接近这种结构的东西都是正当的,但是你可以很容易地发现自己在一个生产规模的应用程序中朝着这个方向前进。

我提供的代码可以用来处理输入和所需的因素。

参见转换和多代码这里

关键点

  • 同样,这也是一个“教学例子”。作为初学者,您不应该期望您的代码看起来像这样。(一步一步:)
  • 相关数据属于同一类型。如果没有前缀名称,这个倍数是没有意义的。

类!

通常,创建表示属于一起的一组值的类型是一个好主意。SI倍数就是这样的例子。"nano“这个名字与它的因素有关。因为它们都构成了一个复合实体或想法,所以它们在类型(structclass)中最有意义,这是我提供的代码中的Multiple类型。

代码语言:javascript
复制
public struct Multiple
{
    public Multiple(string name, int exponent)
    {
        Name = name;
        Exponent = exponent;
    }
    public string Name { get; }  // Read-Only Property
    public int Exponent { get; } // Read-Only Property
    public double Multipler => Math.Pow(10, Exponent);
    public double ConvertToBaseValue(double inputValue)
    {
        return inputValue/Multipler;
    }
    public double ConvertFromBaseValue(double inputValue)
    {
        return inputValue*Multipler;
    }
    public UnitValue CreateValue(double inputValue)
    {
        var newBaseValue = ConvertToBaseValue(inputValue);
        return new UnitValue(this, newBaseValue);
    }
    public static Multiple Singular => new Multiple(null, 0);
    public static Multiple Milli => new Multiple("Milli", -3);
    public static Multiple Micro => new Multiple("Micro", -6);
    public static Multiple Nano => new Multiple("Nano", -9);
    public static Multiple Pico => new Multiple("Pico", -12);
}

同样,您的输入有两个问题(值是多少?)我想看哪一个单元?)然后形成UnitValue类型的基础。如果你把这两个人分开,他们就没什么意义了。

代码语言:javascript
复制
public class UnitValue
{
    public UnitValue(Multiple multiple, double baseValue)
    {
        Multiple = multiple;
        BaseValue = baseValue;
    }
    public Multiple Multiple { get; }
    public double PrefixedValue
    {
        get { return Multiple.ConvertFromBaseValue(BaseValue); }
        set { BaseValue = Multiple.ConvertToBaseValue(value); }
    }
    public double BaseValue { get; set; }
    public UnitValue ConvertTo(Multiple multiple)
    {
        return new UnitValue(multiple, BaseValue);
    }
}

默认值的

静态/类方法

我在Multiple中添加了工厂静态方法来标准化这些值。您可能希望将所有标准定义都内置到该类型中,或者靠近它。

代码语言:javascript
复制
    // Members of Multiple type.
    public static Multiple Singular => new Multiple(null, 0);
    public static Multiple Milli => new Multiple("Milli", -3);
    public static Multiple Micro => new Multiple("Micro", -6);
    public static Multiple Nano => new Multiple("Nano", -9);
    public static Multiple Pico => new Multiple("Pico", -12);
    // Allows you to get multiples like so.
    var m = Multiple.Milli;
    var u = Multiple.Micro;

不要重复了!

每个人都会一遍又一遍地说。在这里,我认为这是通过避免使用所有这些零输入乏味的值来证明的。它还避免了我有0.0001的milli前缀的bug。

代码语言:javascript
复制
    // Risky
    public static Multiple Pico => new Multiple("Pico", 0.000000000001);
    // Safer
    public static Multiple Pico => new Multiple("Pico", -12);

属性访问器

我没有让用户使用特殊的方法来更新基值或前缀值,而是决定将BaseValue属性变成一个自动属性(这意味着我不需要为gettor和settors编写样板代码),并将PrefixedValue连接到它上。通过这种方式,您可以使该类型的用户的生活更容易一些,代价是让他们知道什么时候使用不同的值以及为什么。

代码语言:javascript
复制
    public double PrefixedValue
    {
        get { return Multiple.ConvertFromBaseValue(BaseValue); }
        set { BaseValue = Multiple.ConvertToBaseValue(value); }
    }

只获得属性

因为Multiple数据类型属于一起,所以客户机更新它们没有任何意义。因此,为了防止数据损坏,我让它们只获得在对象实例化时设置的属性。

代码语言:javascript
复制
    // Constructor assigns the values when instantiated.
    public Multiple(string name, int exponent)
    {
        Name = name;
        Exponent = exponent;
    }
    public string Name { get; }  // Can only be set when instantiated.
    public int Exponent { get; } // Can only be set when instantiated.

摘要

当你继续前进的时候,这些是你想要考虑的事情。我跳过了其他一些需要理解的重要事情,但它们可以等到你有了更多的经验之后:

  • 编程到接口,而不是实现。
  • 使用继承专门化(如果我想处理帝国重量)。
  • 使用反射迭代所有预定义的倍数,以便您可以更改定义的倍数,您的UI将自动更新。
  • 单元测试您的代码以验证设计。

我希望那不是太可怕!如果有人有任何反馈的话,我很想听听。

编辑1:添加用法示例

如果使用我编写的类,我已经修改了我在这里的主旨,以包括主程序的一个示例。除了删除复制和将登录的细节推入Log方法之外,我没有在那里进行完整的重构练习。

为什么要替换Console.WriteLine()?这是一个平台函数

的确如此。但你还在到处重复。想象一下,如果你想改变你记录东西的方式?还是添加标准格式?

如果您使实现远离日志记录函数的用户,那么您可以随时更改它。如果您想用日志文件替换控制台日志功能,可以在一个地方更改它。如果没有这个抽象,您就需要更新几十个引用。

代码语言:javascript
复制
    // "Brittle" Code
    Console.WriteLine("Bob");  // In one file
    Console.WriteLine("Says"); // In another file
    Console.WriteLine("Hi!");  // In a third file

    // Abstracted Code
    Log("Bob");
    Log("Bob");

    private static void Log(string message)
    {
        Console.WriteLine(message);
    }

最后一件您还想考虑的事情是,如果用户输入了一些奇怪的内容,会发生什么。此示例不包括用户条目周围的任何错误处理。

票数 10
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/112636

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档