重载与泛型参数

时间:2009-08-24 16:04:12

标签: c# .net vb.net generics overloading

我有一个问题。在框架中,这主要是在泛型来之前编写的,你经常会看到一个有很多重载的函数来做不同类型的事情。

A)

Parse(int data)
Parse(long data)
Parse(string data)
..etc

这似乎没问题,因为它有助于为每种方法保持较小的代码等等。另一方面,现在使用泛型,您可以执行以下操作:

b)中

Parse<T>(T data)

然后使用typeof()创建某种ifs / switch语句,以尝试推断出类型是什么以及如何处理它们。

什么是最佳做法?或者什么是帮助我在a)和b)之间做出选择的想法?

5 个答案:

答案 0 :(得分:20)

恕我直言,如果你需要if / switch语句,你应该更好地重载。如果实现不依赖于具体类型仍然可以重用它,那么应该使用泛型。

作为一般规则:

  • 如果每种类型都有单独的实现
  • ,则重载
  • 如果您可以使用适用于所有可能类型的单个实现,请使用泛型。

答案 1 :(得分:7)

代码嗅觉。

如果你有“某种if / switch ”,那就是尖叫多态的代码味道。它表明泛型不是不是解决该问题的方法。当代码不依赖于您传入的具体类型时,应使用泛型。

观看此Google Tech会谈视频:“The Clean Code Talks -- Inheritance, Polymorphism, & Testing”。它具体针对您所谈论的内容。

答案 2 :(得分:4)

您描述使用泛型导致一堆ifs / switch语句的模式是一种反模式。

对此的一个解决方案是实现一种策略模式,允许您使用泛型,但同时将Parse方法的关注点与知道如何处理每个不同的情况隔离开来。

示例:

class SomeParser
{
    void Parse<T>(ParseStrategy<T> parseStrategy, T data)
    {
        //do some prep

        parseStrategy.Parse(data);

        //do something with the result;
    }
}

class ParseStrategy<T>
{
    abstract void Parse(T data);
}

class StringParser: ParseStrategy<String>
{
    override void Parse(String data)
    {
        //do your String parsing.
    }
}

class IntParser: ParseStrategy<int>
{
    override void Parse(int data)
    {
        //do your int parsing.
    }
}

//use it like so
[Test]
public void ParseTest()
{
    var someParser = new SomeParser();
    someParser.Parse(new StringParser(), "WHAT WILL THIS PARSE TO");
}

然后你就可以传递你开发的任何策略。这样您就可以在多个类中正确地隔离您的问题,而不是违反SRP(单一责任原则。

答案 3 :(得分:2)

这里有一个问题 - 如果你要求/ switch语句使泛型有效,你可能会遇到更大的问题。在这种情况下,很有可能泛型参数不能(正确地)用于每种类型,只是您正在处理的一组固定类型。在这种情况下,您最好提供重载来单独处理特定类型。

这有很多好处:

  • 没有滥用的可能性 - 您是用户无法传递无效的参数
  • 您的API更清晰 - 非常明显哪些类型适合
  • 通用方法使用起来比较复杂,对初学者来说并不那么明显
  • 使用泛型表明任何类型都有效 - 它们确实应该适用于所有类型
  • 通用方法可能会更慢,性能更好

如果你的论证可以用于任何类型,那就不那么清楚了。在这种情况下,我经常会考虑包含重载,以及类型的通用回退方法。当您将“预期”类型传递给方法时,这会提高性能,但您仍然可以使用其他非预期类型。

答案 4 :(得分:1)

虽然没有一个通用的规则,但当特定类型无关时,应使用泛型。这并不是说您不能约束类型,但这种特定类型实际上并不重要。在这种情况下,解析方法完全依赖于每种类型(并且不同)。仿制药似乎不是一个好的解决方案。

相关问题