首页 > 解决方案 > C# 以类特化作为参数重载方法

问题描述

我正在努力解决 C# 中的方法重载问题。

我有几个类继承了一个通用的类

// I can not touch the implementation of these classes
class GenericDataType {}
class ProductDataType : GenericDataType {}
class ContentDataType : GenericDataType {}

还有一个类,它有一个迭代这些类列表的方法。此方法的行为应根据循环当前正在消耗的项目类型而有所不同

class DataTypeParser {
   public List<ParserdType> parseAll(List<GenericDataType> list) {
      var resultList = new List<ParserdType>();
      foreach(var item in list) {
          // if item is a ProductDataType do something
          // if item is a ContentDataType do something else
          // else do some generic stuff...
          // then add to resultList the current processed item
      }
   }
}

我认为最自然的方法是在 GenericDataType 中添加一个虚拟方法,然后在子类中添加该方法的实现,但除了 DataTypeParser 之外,我无法触及任何类。

我不想在代码中添加一堆if else,我宁愿使用一些多态的东西来轻松处理该 GenericDataType 的不同实现。

所以我的解决方案是在 DataTypeParser 中添加一些重载方法

class DataTypeParser {
   public List<ParserdType> parseAll(List<GenericDataType> list) {
      var resultList = new List<ParserdType>();
      foreach(var item in list) {
          var parsed = parse(item);
          if(parsed != null){
              resultList.Add(parsed);
          }
      }
   }
   public ParserdType parse(ProductDataType o){
      // do something
      // ...
      return new ParserdTypeProduct();
   }
   public ParserdType parse(ContentDataType o){
      // do something else
      // ...
      return new ParserdTypeContent();
   }
   public ParserdType parse(GenericDataType o){
      return null;
   }
}

但它不起作用,因为 C# 似乎只调用具有泛型参数的函数。

我错过了什么?

我是个菜鸟,尤其是对于 C#,所以我很容易遗漏一些重要的东西,甚至一些链接也可能很有帮助。

这是 dotnetfiddle 上的示例

标签: c#

解决方案


多态性是运行时的,而方法重载的解决是编译时的,因此您当前的方法当然行不通。

如果你想做“多态的东西”,你需要某种虚拟方法表,你不能使用内置在你拥有的类中的那些,因为你不能修改它们来添加你需要的方法。

相反,您可以创建另一个表,例如

var methodTable = new Dictionary<Type,Action<GenericDataType>>
{
    { typeof(GenericDataType), x => DoParse(x) },
    { typeof(ProductDataType), x => DoParse(x as ProductDataType) },
    { typeof(ContentDataType), x => DoParse(x as ContentDataType) }
};

然后遍历列表并执行:

foreach (var item in list)
{
    methodTable[item.GetType()](item);
}

因为类型是在 lambda 表达式中强制转换的,所以现在将在运行时选择适当的重载。


推荐阅读