首页 > 解决方案 > 处理签名相同但参数含义不同的函数

问题描述

我一直在阅读Robert C. Martin 的Clean Code。他在其中指出,函数应根据需要使用最少数量的参数,并且函数名称应遵循项目范围的命名约定,同时避免无缘无故的上下文。

例如,如果我为这个问题编写了一个简单的类,则Car

public class Car
    {
        internal string make { get; set; }
        internal string model { get; set; }

        public Car(string make, string model)
        {
            this.make = make;
            this.model = model;
        }
    }

还有一个类Cars

public class Cars
{
    internal List<Car> cars { get; set; }

    public Cars(List<Car> cars)
    {
        this.cars = cars;
    }

    public Car GetCar(string make)
    {
        foreach (Car car in cars)
        {
            if (car.make == make) return car;
        }
        return null;
    }

    public Car GetCar(string model)
    {
        foreach (Car car in cars)
        {
            if (car.model == model) return car;
        }
        return null;
    }

}

显然这不会编译,因为命名的函数GetCar具有相同的函数签名。

通常我可能已经通过重命名函数GetCarByMakeandGetCarByModel或类似的东西来解决这个问题,但文本似乎表明这不是最佳实践。其他时候,我可能添加了一个额外的未使用参数来区分它们。

Car我的下一个想法是为;中的每个属性创建一个类。有一个包含字符串属性的Make类。Model但是,这似乎引入了不必要的开销。

那我很好奇,我怎样才能实现/命名多个函数,这些函数通常做类似的事情,具有相同的参数数据类型,并输出相同的数据类型,而没有不同的函数名称?此外,我对这个问题或类似主题的额外函数重载或多态性不感兴趣;我想知道关于这些课程的答案,因为它们目前没有重大变化。我目前能看到的唯一答案是为每个属性创建类。

如果需要任何澄清或更改,请告诉我。

编辑:正如一些附加信息,这纯粹是一个学术练习。从专业上讲,我会简单地创建具有不同名称的方法并完成它。正如评论中所述,它简单、可维护且有效。

标签: c#architecturesoftware-design

解决方案


通过显式接口实现,可以在同一个类中拥有多个具有相同“名称”和签名的方法:

public interface IFindByMake
{
     Car GetCar(string make);
}

public interface IFindByModel
{
     Car GetCar(string model);
}

public class Cars : IFindByMake, IFindByModel
{
    internal List<Car> cars { get; set; }

    public Cars(List<Car> cars)
    {
        this.cars = cars;
    }

    Car IFindByMake.GetCar(string make)
    {
        foreach (Car car in cars)
        {
            if (car.make == make) return car;
        }
        return null;
    }

    Car IFindByModel.GetCar(string model)
    {
        foreach (Car car in cars)
        {
            if (car.model == model) return car;
        }
        return null;
    }
}

上面的代码可以编译;但是,您会注意到,如果您声明一个类型的变量,Cars将没有GetCar可用的方法。如果您强制转换为两种接口类型之一或将变量声明为两种类型之一,则只能调用该方法。

var cars = new Cars();
((IFindByMake)cars).GetCar(“Ford”);

或者

IFindByModel cars = new Cars();
cars.GetCar(“Mustang”);

否则编译器到底怎么知道要调用哪个方法?


推荐阅读