题
我有一个结构的名称空间,这些名称空间代表各种度量单位(仪表,脚,英寸等)...总共12个,由T4模板产生,由T4模板产生。:)。
每个结构都带有隐性铸造操作员,以支持将价值铸造为其他任何测量值类型,因此以下Sytax是合法的:
var oneThousandMeters = new Meters(1000);
Kilometers aKilo = oneThousandMeters ; // implicit cast OK. Value = 1 Km
为了增加喜悦,有一个叫做全部的班级 距离 它可以容纳任何度量单位,也可以隐含地施放和从测量值进行。
var magnum = new Distance(12, DistanceUnits.Inches);
Feet wifesDelight = magnum; // implicit cast OK. Value = 1 foot.
遵循.NET框架标准,所有字符串格式和解析均由外部A FormatProvider处理,该格式化的形式实现了IcustomFormatter。可悲的是,这意味着当值传递给格式方法时,将其盒装,并且格式方法需要在每个已知的测量类型上对对象进行测试,然后才能对其作用。在内部,格式方法无论如何都将测量值施加到距离值,因此问题出现在这里。
问题:
public string Format(string format, object arg, IFormatProvider formatProvider)
{
Distance distance;
// The following line is desired, but fails if arg != typeof(Distance)
distance = (Distance)arg;
// But the following tedious code works:
if(arg is Distance)
distance = (Distance)arg;
else if(arg is Meters)
distance = (Distance)(Meters)arg; // OK. compile uses implicit cast.
else if(arg is Feet)
distance = (Distance)(Feet)arg; // OK. compile uses implicit cast.
else if(arg is Inches)
distance = (Distance)(Inches)arg; // OK. compile uses implicit cast.
else
... // tear you hair out for all 12 measurement types
}
是否有任何解决方案,或者这仅仅是价值类型的缺点之一?
PS:我已经检查了 这个帖子, ,尽管问题是相似的,但这并不是我想要的。
解决方案
好吧,这是将拆箱转换与用户定义的转换分开的问题。您希望两者都会发生 - 并且必须指定输入的类型,并让编译器知道何时需要用户定义的转换。用户定义的转换必须在 编译 除非您使用动态键入,否则编译器需要知道它要转换的类型。
一种选择是有一个 IDistance
界面 所有结构都实现了。然后,您可以使用:
IDistance distanceArg = arg as IDistance;
if (distanceArg != null)
{
Distance distance = distanceArg.ToDistance();
}
由于您已经拥有盒装值,因此使用接口不会引起额外的拳击或类似的东西。每个 ToDistance
实施可能只能使用隐式转换:
public Distance ToDistance()
{
return this;
}
...或者您可以进行转换 ToDistance
.
其他提示
是的,这只是您必须忍受的事情之一。
如果将整数推入对象:
int a = 0;
object b = a;
int c = (int)b; // this works
short d = (short)b; // this fails
short e = (short)(int)b; // this works
不隶属于 StackOverflow