V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
richards64
V2EX  ›  程序员

求问一道 C#笔试题,想知道最好的解答是什么

  •  1
     
  •   richards64 · 2020-09-16 20:28:02 +08:00 · 2495 次点击
    这是一个创建于 1316 天前的主题,其中的信息可能已经有所发展或是发生改变。

    题目如下:

    这是一段用于计算多个几何形状面积之和的程序

    1. 指出程序段存在的不妥之处,并重构代码
    2. 在 1 的基础上增加一种可计算的几何形状类型三角形,其面积为 底×高×1/2
    public class Shape
    {
        public int Type { get; set; }
        public int Radius { get; set; }
        public int Width { get; set; }
        public int Length { get; set; }
    }
    
    public class ShapeCalculator
    {
        public static double CalculateTotalArea(List<Shape> shapes)
        {
            double totalArea = 0;
            if (shapes != null && shapes.Count() > 0)
            {
                foreach (Shape shape in shapes)
                {
                    if (shape.Type == 1)
                    {
                        totalArea += Math.PI * shape.Radius * shape.Radius;
                    }
                    else if (shape.Type == 2)
                    {
                        totalArea += shape.Length * shape.Width;
                    }
                }
            }
            return totalArea;
        }
    }
    

    我的回答是这样的:

    interface ICalc
    {
        double GetAera();
    }
    
    class Circle : ICalc
    {
        public int Radius { get; set; }
    
        public double GetAera()
        {
            return Math.PI * Radius * Radius;
        }
    }
    
    class Rectangle : ICalc
    {
        public int Length { get; set; }
        public int Width { get; set; }
    
        public double GetAera()
        {
            return Length * Width;
        }
    }
    
    class Triangle : ICalc
    {
        public int Bottom { get; set; }
        public int Height { get; set; }
    
        public double GetAera()
        {
            return Bottom * Height * 0.5;
        }
    }
    
    class ShapeCalculator
    {
        public static double CalculateTotalArea(List<ICalc> shapes)
        {
            double totalArea = 0;
            if (shapes != null)
            {
                totalArea = shapes.Sum(shape => shape.GetAera());
            }
            return totalArea;
        }
    }
    

    凭我的水平和理解能力就只有写到这种程度了……有什么更好的写法吗?

    16 条回复    2020-09-17 16:23:43 +08:00
    across
        1
    across  
       2020-09-16 21:28:51 +08:00 via Android
    我猜原意不止 oop,还要你改几个细节,比如 int 应该是 float,面积 float 精度就足够。
    forgottencoast
        2
    forgottencoast  
       2020-09-16 23:05:26 +08:00
    源代码最主要的问题就是每增加一个 Shape,都要改动 CalculateTotalArea 方法。
    写法很多,你这个写法可以了。
    剩下的就是细节问题了,比如#1 所说的,Width 和 Length 用 int 肯定不妥。
    CalculateTotalArea 接收的参数类型要更抽象一点,List<T>肯定不好。
    你定义的接口 ICalc 命名太宽,和方法名 GetArea 不够匹配。
    richards64
        3
    richards64  
    OP
       2020-09-16 23:30:34 +08:00
    @forgottencoast CalculateTotalArea(IEnumerable<ICalc> shapes) 好一点?
    andrewpsy
        4
    andrewpsy  
       2020-09-17 00:15:59 +08:00 via Android
    上面都说的很好了,还有个可能是面试官想测你知不知道 strategy pattern 。你要是想 over engineering 可以实现一下玩玩。
    richards64
        5
    richards64  
    OP
       2020-09-17 00:38:58 +08:00
    @andrewpsy 实际情况是面试官好像对我的回答没有什么异议,对我的 C#基础还是挺满意的,但是最后拒掉了我的理由是因为这个岗位需要精通 SQL 优化,这我就不会了……
    yazoox
        6
    yazoox  
       2020-09-17 08:29:05 +08:00
    这就是“十动然拒”?
    奇怪,如果岗位是对 SQL 技能有特别需求,一开始知道你不会(比如:简历),那还面试啥?这不是浪费大家时间么?
    Rwing
        7
    Rwing  
       2020-09-17 08:48:50 +08:00
    挺好的,我觉得 HR 只是不想招人,换公司继续面吧
    forgottencoast
        8
    forgottencoast  
       2020-09-17 09:28:48 +08:00
    @richards64 #3
    是的。
    越抽象的接口适用范围越广,如果你用不到更具体接口的其他成员,就应该用更抽象的接口。
    IEnumerable<T>是最抽象的接口了,所有的泛型集合都实现了它,一般设计时可以考虑先用它,除非它不符合需求,再考虑更具体的接口。
    yamatamain
        9
    yamatamain  
       2020-09-17 09:35:36 +08:00
    @richards64 总会有一个理由。
    SWALLOWW
        10
    SWALLOWW  
       2020-09-17 09:45:43 +08:00
    第一眼 shapes.Count()有问题...
    beingWH
        11
    beingWH  
       2020-09-17 09:57:28 +08:00
    感觉问题不大。
    beingWH
        12
    beingWH  
       2020-09-17 10:11:35 +08:00
    ```
    interface ICalc
    {
    float GetAera();
    }

    class Circle : ICalc
    {
    public float Radius { get; set; }

    public float GetAera()
    {
    return Math.PI * Radius * Radius;
    }
    }

    class Rectangle : ICalc
    {
    public float Length { get; set; }
    public float Width { get; set; }

    public float GetAera()
    {
    return Length * Width;
    }
    }

    class Triangle : ICalc
    {
    public float Bottom { get; set; }
    public float Height { get; set; }

    public float GetAera()
    {
    return Bottom * Height * 0.5;
    }
    }

    static class ShapeCalculator
    {
    public static float CalculateTotalArea(this List<ICalc> shapes)
    {
    float totalArea = 0;
    if (shapes != null)
    {
    totalArea = shapes.Sum(shape => shape.GetAera());
    }
    return totalArea;
    }
    }
    ```
    kop1989
        13
    kop1989  
       2020-09-17 10:20:37 +08:00
    我有个想法不知道对不对。

    觉得可以在你的基础上再添加一个 Shape 转换为 ICalc 实现类的逻辑。
    因为从实际项目的角度讲,你再怎么重构,数据源也是不变的。
    你这个重构最终丢了逻辑。既你把 ICalc 的实现类抉择抛给了调用 CalculateTotalArea 的人。
    原来的数据源是 List<Shape>。现在传进来的还应该是 List<Shape>。
    Caskia
        14
    Caskia  
       2020-09-17 10:55:52 +08:00
    @richards64 拒绝的问题应该不在你这个回答上面,敢问这是哪家的面试题?
    richards64
        15
    richards64  
    OP
       2020-09-17 16:20:10 +08:00
    @kop1989 这个没太看明白,能具体演示一下吗
    richards64
        16
    richards64  
    OP
       2020-09-17 16:23:43 +08:00
    @Caskia 确实挺奇怪的,我看 JD 上有要求掌握 WPF 就投了简历,简历上也表示出了我只有 WPF 经历,然后就让我去面试了,去了之后发现实际的主要工作内容是.NET Core 的后端开发,只是个别项目组有少量的老旧项目涉及到 WPF
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3673 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 10:39 · PVG 18:39 · LAX 03:39 · JFK 06:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.