这种模式有名字吗?
假设您想要创建一个采用可变数量参数的方法,每个参数都必须是一组固定类型(以任何顺序或组合)之一,并且其中一些类型您无法控制。一种常见的方法是让您的方法采用 Object 类型的参数,并在运行时验证类型:
void MyMethod (params object[] args)
{
foreach (object arg in args)
{
if (arg is SomeType)
DoSomethingWith((SomeType) arg);
else if (arg is SomeOtherType)
DoSomethingElseWith((SomeOtherType) arg);
// ... etc.
else throw new Exception("bogus arg");
}
}
但是,假设您像我一样痴迷于编译时类型安全,并且希望能够在编译时验证方法的参数类型。这是我想出的一种方法:
void MyMethod (params MyArg[] args)
{
// ... etc.
}
struct MyArg
{
public readonly object TheRealArg;
private MyArg (object obj) { this.TheRealArg = obj; }
// For each type (represented below by "GoodType") that you want your
// method to accept, define an implicit cast operator as follows:
static public implicit operator MyArg (GoodType x)
{ return new MyArg(x); }
}
隐式转换允许您将有效类型的参数直接传递到例程,而无需显式转换或包装它们。如果尝试传递不可接受类型的值,则会在编译时捕获错误。
我确信其他人已经使用过这种方法,所以我想知道这种模式是否有一个名称。
互联网上似乎没有命名模式,但基于Ryan https://stackoverflow.com/users/864087/ryan-russell对你的问题的评论,我投票模式的名称应该是Variadic https://en.wikipedia.org/wiki/Variadic_function类型安全.
一般来说,我会非常谨慎地使用它,但我不会判断该模式的好坏。许多评论者都提出了赞成和反对的好观点,我们在其他模式中也看到了这一点,例如Factory, 服务定位器, 依赖注入, MVVM等等。这都是关于上下文的。所以这是一个尝试......
Context
必须处理不同对象的可变集合。
Use When
- 您的方法可以接受不同数量的不具有公共基类型的不同类型的参数。
- 您的方法被广泛使用(即在代码中的许多地方和/或框架的大量用户)。重点是类型安全性提供了足够的好处来保证其使用。
- 参数可以按任何顺序传递,但不同类型的集合是有限的,并且是该方法可接受的唯一集合。
- 表现力是您的设计目标,您不想让用户承担创建包装器或适配器的责任(请参阅备择方案).
执行
你已经提供了。
Examples
- LINQ 到 XML(例如
new XElement(...)
)
- 其他构建器,例如构建 SQL 参数的构建器。
- 处理器外观(例如,那些可以接受来自不同框架的不同类型的委托或命令对象的处理器外观)来执行命令,而无需创建显式命令适配器。
备择方案
-
Adapter。接受某种适配器类型的可变数量的参数(例如
Adapter<T>
或非泛型的子类Adapter
)该方法可以用来产生所需的结果。这扩大了您的方法可以使用的集合(类型不再是有限的),但如果适配器执行正确的操作以使处理仍然有效,则不会丢失任何内容。缺点是用户有指定现有和/或创建新适配器的额外负担,这可能会偏离意图(即增加“仪式”,并削弱“本质”)。
-
删除类型安全。这需要接受一个非常基本的类型(例如
Object
)并进行运行时检查。需要传递什么信息的负担被传递给用户,但代码仍然具有表现力。错误直到运行时才会显现出来。
-
合成的。传递由其他对象组合而成的单个对象。这需要方法调用前的构建,但又会返回到对组合集合中的项目使用上述模式之一。
-
流畅的API。将单个调用替换为一系列特定调用,每个调用对应一种可接受的参数类型。一个典型的例子是
StringBuilder
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)