【问题标题】:C#: is System.Type not a real type? or: working around single dispatchC#:System.Type 不是真正的类型吗?或:解决单一调度问题
【发布时间】:2014-12-08 15:16:36
【问题描述】:

我一直在尝试解决没有基于方法参数类型的多态分派的 C# 问题,但我遇到了您无法传递类型的问题。

我基本上有一个抽象类Model,它实现了两种方法:IEnumerable<Decision> GetDecisions()void TakeDecision(Decision decision)Decision 也是一个抽象类。这个类的消费者反复获得可能的决定,评估它们并将最好的决定传回Model

每个单独的派生模型都可以处理一些常见的决策和一些特定于模型的决策,对于每个 Decision 类型,我有一个单独的 TakeDecision() 方法,这个特定的 Model 可以使用。问题当然是单次调度。理想情况下,消费者会这样做:

var m = ModelFactory.GetModel(some parameters); //m is type Model var ds = m.GetDecisions(); //ds is IEnumerable<Decision> //Some logic here to choose the best Decision d m.TakeDecision(d);

现在我必须在每个派生的 Model 中实现看起来像这样的逻辑,因为 C# 可以分派到正确的 Model 实现,但不能分派到正确的重载:

if (decision is FooDecision) TakeDecision((FooDecision)decision); if (decision is BarDecision) TakeDecision((BarDecision)decision); ...

或者我强迫消费者站在他们这边(他们很可能已经这样做了以检查决定)。

我想在每个派生类中都有一个System.Types 列表,所以我可以这样做:

foreach (var t in AllowedDecisionTypes) { if (decision is t) TakeDecision((t)decision); }

但看起来System.Type 不是真正的类型:

  1. 你不能这样做:AllowedDecisionTypes.Add(FooDecision),但你可以这样做AllowedDecisionTypes((new FooDecision()).GetType())
  2. 反之亦然,您不能使用decision is AllowedDecisionTypes[0],但可以使用decision is FooDecision

有没有办法两者兼得?即,生成类型列表并转换为它们?或者是在每个决策上进行双重分派并实施void Decision.ApplyTo(Model model) { model.TakeDecision(this); } 的唯一方法,这可能应该分派到正确的重载,因为this 现在是特定的Decision

【问题讨论】:

    标签: c# polymorphism type-conversion multiple-dispatch


    【解决方案1】:

    要将Type 添加到Type 对象列表中,您只需使用typeof 运算符,而不仅仅是添加类型。

    对于Type 对象,与is 等效的操作是使用其IsAssignableFrom 方法。

    您将无法根据Type 投射对象;基于Type 调用多个重载之一的方法是通过反射。

    【讨论】:

    • 您对在不使用反射的情况下调用正确重载的正确方法有什么建议吗?
    • @Alexey 没办法。你需要使用反射。
    【解决方案2】:

    Type 是描述某种类型的对象,但如果我们这样看,它不是类型本身:String != typeof(String)

    你可以这样做:

    // Add type to collection of Type
    AllowedDecisionTypes.Add(typeof(FooDecision))
    
    // Check if the current decision EXACTLY of the same type
    if(myDecision.GetType() == AllowedDecisionTypes[0])
    
    // Check if the current decision inherits/implements that type (like using the 'is' operator)
    if(AllowedDecisionTypes[0].IsAssignableFrom(myDecision.GetType()))
    

    【讨论】:

      猜你喜欢
      • 2014-06-22
      • 2012-01-25
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-11
      • 2015-04-26
      相关资源
      最近更新 更多