双调度和替代品 [英] Double-dispatch and alternatives

查看:151
本文介绍了双调度和替代品的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到一种更好的方式来处理一些成长如果构造处理类不同的类型。这些类是,最终,围绕不同的值类型(int,日期时间等)与一些附加的状态信息的封装。因此,这些类之间的主要区别是数据的它们包含的类型。虽然他们实施通用接口,他们还需要保持在均匀的集合,因此它们也实现非泛型接口。类的实例是根据数据的它们重新present及其传播史继续或不继续基于类型来处理。

I am trying to find a better way to handle some growing if constructs to handle classes of different types. These classes are, ultimately, wrappers around disparate value types (int, DateTime, etc) with some additional state information. So the primary difference between these classes is the type of data they contain. While they implement generic interfaces, they also need to be kept in homogeneous collections, so they also implement a non-generic interface. The class instances are handled according to the type of data they represent and their propogation continues or doesn't continue based on that.

虽然这并不一定是.NET和C#的问题,我的code是在C#。

While this is not necessarily a .NET or C# issue, my code is in 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) ...
}

我已经提出了两个选项:

I have come up with two options:

双调度

我最近才知道的访问者模式及其使用双重分派来处理这样一个情况。这种呼吁,因为这将允许不需要的数据,不会传播(如果我们只是想处理一个int,我们可以处理不同于一个DateTime)。另外,如何在不同的类型的处理的行为将限于正在处理调度的单个类。但是,维护公平一点,如果/当一个新的值类型必须是支持的。

I recently learned of the Visitor pattern and its use of double dispatch to handle just such a case. This appeals because it would allow undesired data to not propogate (if we only want to handle an int, we can handle that differently than a DateTime). Also, the behaviors of how the different types are handled would be confined to the single class that is handling the dispatch. But there is a fair bit of maintenance if/when a new value type has to be supported.

联盟类

这包含了支持的可能是什么每个类店的每个值类型的属性的类。在值的任何操作都会影响相应的组件。这是一个不太复杂和维护比双分派策略较少,但它意味着,每一个数据都将propogate一路过关斩将不必要的,你不能再沿着我不根据数据类型进行操作的行歧视。但是,如果/当新类型需要支持,他们只需要进入这个类(加上任何需要创建以支持新的数据类型的其他类)。

A class that contains a property for each value type supported could be what each of these classes store. Any operation on a value would affect the appropriate component. This is less complex and less maintenance than the double-dispatch strategy, but it would mean that every piece of data would propogate all the way through unnecessarily as you can no longer discriminate along the lines of "I don't operate upon that data type". However, if/when new types need to be supported, they only need to go into this class (plus whatever additional classes that need to be created to support the new data type).

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

有没有更好的选择?有什么在任这两个选项,我不认为我应该?

Are there better options? Is there something in either of these two options that I did not consider that I should?

推荐答案

方法1,采用动态双分派(归功于的http://blogs.msdn.com/b/curth/archive/2008/11/15/c-dynamic-and-multiple-dispatch.aspx). 基本上,你可以有你的访问者模式简化是这样的:

method 1, using dynamic for double dispatch (credit goes to http://blogs.msdn.com/b/curth/archive/2008/11/15/c-dynamic-and-multiple-dispatch.aspx). Basically you can have your Visitor pattern simplified like this:

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#中所提出的@Juliet 这里(另一种实现这里

这篇关于双调度和替代品的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆