处理具有相同签名但参数含义不同的函数

时间:2018-10-30 20:24:56

标签: c# architecture software-design

我一直在读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的函数具有相同的函数签名。

通常我可以通过重命名功能GetCarByMakeGetCarByModel或类似的方法来解决此问题,但是文本似乎表明这不是最佳实践。其他时候,我可能添加了其他未使用的参数来区分它们。

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

那么,我很好奇,我如何实现/命名具有常规相似功能,具有相同参数数据类型并输出相同数据类型而又没有不同函数名称的多个函数?另外,对于这个问题或类似主题,我对其他函数重载或多态性也不感兴趣。我想知道有关这些类的答案,因为它们目前没有重大变化。我目前只能看到的唯一答案是为每个属性创建类。

请让我知道是否需要任何澄清或更改。

编辑: 正如一些补充信息一样,这纯粹是一项学术活动。专业上,我只是用不同的名称创建方法并完成它。如评论中所述,它简单,可维护且有效。

2 个答案:

答案 0 :(得分:3)

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

Laravel

上面的代码可以编译;但是,您会注意到,如果声明类型为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”);

否则,编译器将如何知道要调用哪个方法?

答案 1 :(得分:1)

您可以按如下所述使用linq

public Car GetCar(string make, string model)
{

    return cars.Where(w=>  (string.IsNullOrEmpty(make) || w.make == make) &&(string.IsNullOrEmpty(model) || w.model == model)).Select(s=>s).FirstOrDefault();
}