在vb.net中,可以设计一个可以对满足多个约束的通用参数进行操作的函数。例如,有一个函数可以接受一个继承自Control并实现IList的类作为参数。此函数可以在此类对象上使用“Control”或“IList”方法,并将对象传递给期望Control或IList的任何内容[请注意,选择此特定组合是为了方便一个简短的示例,而不是特别的有用的组合]。
Sub CrossThreadAdd(Of T, U As {Control, IList(Of T)})(ByVal TheControl As U, ByVal NewThing As T) If TheControl.InvokeRequired Then TheControl.BeginInvoke(New Action(Of U, T)(AddressOf CrossThreadAdd), TheControl, NewThing) Else TheControl.Add(NewThing) End If End Sub
这种方法提供了编译时类型安全性;没有必要在运行时失败。另一种方法是将参数作为Control或IList传递,并将函数转换为另一个。但是,如果传递的对象实际上不满足这两个约束,那么它将在运行时失败。
在什么情况下使用像上面这样的通用函数是好的,在什么情况下,让满足两个约束的对象都有一个新的接口,比如IListableControl(Of T),它将包含一个TheControl将返回自身的属性(作为控件进行转换),以及在什么情况下拥有通用的ISelf(of T)接口会更好,其中任何实现者都应该提供一个“Self”属性,该属性将自身返回为一个T?
使用多约束泛型,可以在不需要任何运行时类型转换的情况下执行大量操作,但我不知道性能成本可能是多少。我尝试编写一个简短的程序,在运行时生成65,536种不同的泛型类型,例如: Foo(Bar(Of Foo)(Of Of Foo(Of Foo)(...(Blah))))))),它很慢,所以我可以告诉处理泛型所需的时间不是固定的,但我不知道是什么因素影响它。
答案 0 :(得分:1)
对于通用函数而言, no 运行时旁边应该存在正常函数。同样,约束的数量在运行时完全没有影响 - 它由编译器检查。当您使用反射来访问这些函数时,当然会有不同的东西。
关于这些限制有用的问题......
就个人而言,我会说:经常。接口应该只模拟一个关注点。聚合接口(例如IListableControl
)听起来就像代码味道(当然,这假设存在具有多个约束的泛型,否则它们实际上可能是提供类型安全性所必需的。)