来自于C#和Java背景,我习惯于我的列表是同构的,这对我来说是有意义的。当我开始使用Lisp时,我注意到列表可以是异构的。当我开始在dynamic
中乱搞C#关键字时,我注意到,在C# 4.0中,也可以有异构列表:
List<dynamic> heterogeneousList
我的问题是什么是重点?在进行处理时,异构列表的开销似乎要大得多,而且如果需要在一个地方存储不同的类型,则可能需要不同的数据结构。我的天真是在丑恶的脸上培养出来的,还是真的有必要有一个不同的列表呢?
发布于 2012-02-01 16:18:09
Oleg、拉尔夫·L、基恩·舒普克的论文“强类型异源集合”不仅包含了Haskell中异构列表的实现,而且还包含了一个关于何时、为什么以及如何使用HLists的令人鼓舞的例子。特别是,他们正在使用它进行类型安全编译时检查数据库访问。(想想LINQ,事实上,他们所引用的论文是Erik Meijer等人的Haskell论文,它导致了LINQ。)
引用HLists文件导言段的话:
以下是需要异构集合的典型示例的开放列表:
请注意,在您的问题中给出的例子实际上并不是异类列表,因为这个词是常用的。它们是弱类型或非类型化列表。事实上,它们实际上是同质列表,因为所有元素都是相同类型的:object
或dynamic
。然后,您将被迫执行强制转换或未检查的instanceof
测试或类似的操作,以便能够真正有意义地使用元素,这使得它们的类型比较弱。
发布于 2012-02-01 14:39:45
长话短说,异构容器以运行时性能换取灵活性。如果你想要一个“材料列表”而不考虑特定类型的东西,那么异质性就是最好的选择。list是动态输入的,而且大多数东西都是一个缺点--无论如何都是盒装值的列表,因此,对性能的影响是很小的。在Lisp世界中,程序员的生产力被认为比运行时性能更重要。
在动态类型化语言中,与异构容器相比,同构容器实际上具有较小的开销,因为添加的所有元素都需要进行类型检查。
关于选择更好的数据结构,您的直觉是正确的。一般来说,您可以在代码上设置的契约越多,您就越了解它是如何工作的,并且它变得更可靠、更易于维护。但是,有时您确实需要一个异构容器,如果需要的话,应该允许您拥有它。
发布于 2012-02-01 14:52:38
在函数式语言(如lisp)中,使用模式匹配来确定列表中的特定元素发生了什么。在C#中等效的是一个if...elseif语句链,它检查元素的类型并在此基础上执行操作。不用说,函数模式匹配比运行时类型检查更有效。
使用多态性将更接近模式匹配。也就是说,让列表中的对象匹配一个特定的接口,并在该接口上为每个对象调用一个函数。另一种选择是提供一系列以特定对象类型作为参数的重载方法。以对象作为其参数的默认方法。
public class ListVisitor
{
public void DoSomething(IEnumerable<dynamic> list)
{
foreach(dynamic obj in list)
{
DoSomething(obj);
}
}
public void DoSomething(SomeClass obj)
{
//do something with SomeClass
}
public void DoSomething(AnotherClass obj)
{
//do something with AnotherClass
}
public void DoSomething(Object obj)
{
//do something with everything els
}
}
这种方法提供了对Lisp模式匹配的近似。访问者模式(在这里实现的,是使用异构列表的一个很好的例子)。另一个例子是消息调度,在这种情况下,在优先级队列中有特定消息的侦听器,并使用责任链,调度程序传递消息,第一个与消息匹配的处理程序处理消息。
另一方面是通知为消息注册的每个人(例如,事件聚合器模式通常用于ViewModels模式中的松散耦合)。我使用以下构造
IDictionary<Type, List<Object>>
添加到字典的唯一方法是一个函数。
Register<T>(Action<T> handler)
(对象实际上是传入处理程序的WeakReference )。所以在这里我必须使用List,因为在编译时,我不知道封闭类型是什么。然而,在运行时,我可以强制它是字典的关键。当我想启动我所呼吁的事件时
Send<T>(T message)
我再一次解决这个问题。使用List没有任何好处,因为我无论如何都需要转换它。因此,正如你所看到的,这两种方法都有其优点。如果要使用方法重载动态地分派一个对象,动态就是这样做的。如果你被迫抛砖引玉,不妨使用Object。
https://softwareengineering.stackexchange.com/questions/132835
复制相似问题