我试图找到一种更好的方法来处理一些增长的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) ...
}
我提出了两种选择:
双重调度
我最近了解了Visitor模式及其使用双重调度来处理这种情况。之所以具有吸引力,是因为它将允许不想要的数据不传播(如果我们只想处理一个int,则可以与DateTime进行不同的处理)。同样,如何处理不同类型的行为将被限制在处理分派(dispatch)的单个类中。但是,如果/当必须支持新的值类型时,则需要大量维护。
联合类
每个支持的值类型都包含一个属性的类可能就是这些类中的每个存储的内容。对值的任何运算都会影响适当的组件。与双重调度策略相比,此方法不那么复杂且维护较少,但是这意味着每条数据都将不必要地一直传播,因为您将无法再按照“我不对那种数据类型进行操作”来区分。 ”。但是,如果/当需要支持新类型时,它们仅需要进入此类(加上需要创建以支持新数据类型的任何其他类)。
class UnionData {
public int NumericValue;
public DateTime DateTimeValue;
}
有更好的选择吗?这两个选项中有一个我不认为应该做的事情吗?
最佳答案
方法1,使用dynamic进行双重调度(贷记到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将使用@Juliet here提出的C#中的Union类型(替代实现here)
关于c# - 双重 dispatch 和替代,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9502915/