c# - 双重 dispatch 和备选方案

标签 c# .net double-dispatch

我正在尝试找到一种更好的方法来处理一些不断增长的 if 结构,以处理不同类型的类。这些类最终是具有一些附加状态信息的不同值类型(int、DateTime 等)的包装器。因此,这些类之间的主要区别在于它们包含的数据类型。虽然它们实现了泛型接口(interface),但它们也需要保存在同构集合中,因此它们也实现了一个非泛型接口(interface)。类实例根据它们表示的数据类型进行处理,并且它们的传播继续或不继续基于该类型。

虽然这不一定是 .NET 或 C# 问题,但我的代码是在 C# 中。

示例类:

interface ITimedValue {
 TimeSpan TimeStamp { get; }
}

interface ITimedValue<T> : ITimedValue {
 T Value { get; }
}

class NumericValue : ITimedValue<float> {
 public TimeSpan TimeStamp { get; private set; }
 public float Value { get; private set; }
}

class DateTimeValue : ITimedValue<DateTime> {
 public TimeSpan TimeStamp { get; private set; }
 public DateTime Value { get; private set; }
}

class NumericEvaluator {
 public void Evaluate(IEnumerable<ITimedValue> values) ...
}

我有两个选择:

双重 dispatch

我最近了解到访问者模式及其使用双重分派(dispatch)来处理这种情况。这很有吸引力,因为它会允许不需要的数据不传播(如果我们只想处理一个 int,我们可以用不同于 DateTime 的方式处理它)。此外,如何处理不同类型的行为将仅限于处理分派(dispatch)的单个类。但是,如果/当必须支持新的值类型时,需要进行一些维护工作。

联合类

包含每个支持的值类型的属性的类可以是这些类中的每一个存储的内容。对值的任何操作都会影响相应的组件。这比双分派(dispatch)策略更简单,维护更少,但这意味着每条数据都会不必要地一直传播,因为您不能再按照“我不对该数据类型进行操作”的方式进行区分”。但是,如果/当需要支持新类型时,它们只需要进入此类(加上需要创建的任何其他类来支持新数据类型)。

class UnionData {
 public int NumericValue;
 public DateTime DateTimeValue;
}

有更好的选择吗?这两个选项中是否有我认为不应该做的事情?

最佳答案

方法 1,使用动态进行双重分派(dispatch)(致谢 http://blogs.msdn.com/b/curth/archive/2008/11/15/c-dynamic-and-multiple-dispatch.aspx )。 基本上你可以像这样简化你的访客模式:

class Evaluator {
 public void Evaluate(IEnumerable<ITimedValue> values) {
    foreach(var v in values)
    {
        Eval((dynamic)(v));
    }
 }

 private void Eval(DateTimeValue d) {
    Console.WriteLine(d.Value.ToString() + " is a datetime");
 }

 private void Eval(NumericValue f) {
    Console.WriteLine(f.Value.ToString() + " is a float");
 }

}

使用示例:

var l = new List<ITimedValue>(){
    new NumericValue(){Value= 5.1F}, 
    new DateTimeValue() {Value= DateTime.Now}};

new Evaluator()
    .Evaluate(l);
       // output:
       // 5,1 is a float
       // 29/02/2012 19:15:16 is a datetime

方法 2 将在 c# 中使用 Union 类型,正如@Juliet 所提议的那样 here (替代实现 here )

关于c# - 双重 dispatch 和备选方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9502915/

相关文章:

c# - 如何在生产环境中调试 C# Windows 窗体应用程序?

c# - 消息框和单元测试

c# - 将 C 结构编码为 C# 委托(delegate)的返回值

c++ - 了解双重调度 C++

c++ - 我们在 C++ 中需要双重调度/访问者到底发生了什么

c# - 使用 Ajax 将 json 从 Javascript 返回到 aspx

c# - 访问基类变量不可访问错误

.net - 希腊增值税验证码

c# - 变量名不能以 'm_' : StyleCop Rule 1308 - Why is it considered a bad (or not good/standard) practice? 开头

c# - .Net 4.0 重构现有 "if"条件和 "is"运算符的优化代码