假设我们有一个允许隐式转换为某种类型的结构,比如说'string',如下所示。
public struct Foo
{
public string Value;
public static implicit operator string(Foo i)
{
return i.Value;
}
}
让iFoo
成为Foo
的实例。根据此定义,后续方法调用的赋值如
string Test = iFoo;
Test = Test.Trim();
在语法上是正确的,而像
这样的合同调用string Test = iFoo.Trim();
不是。这是什么原因?是否可以通过隐式转换实现所需的行为(在string
的实例上调用Foo
方法的可能性)?如果没有,第二段代码在语法上是不正确的原因是什么?
答案 0 :(得分:3)
不,方法调用将使用不同的规则完成,并且不涉及类似的投射。如果没有你,你将无法做到:
答案 1 :(得分:1)
隐式演员允许两件事:
好吧,这听起来有点同义,但是让我们一次拍摄那些,演员表演。
因为你可以做演员:
string Test = ((string)iFoo).Trim();
这是有效的,因为表达式((string)iFoo)
有一个已定义的工作方式(因为强制转换),当你将表达式((string)iFoo).Trim()
分解为由它组成的表达式时,所有这些都是句法和有意义的,并已定义行为。
现在,隐式部分是,作为语法糖,我们可以省略(string)
部分,在某些情况下执行此 。这通常是因为"扩大"所涉及的转换是如此明显,以至于演员会(或至少可以说可能)分散程序员的注意力而不是让事情清楚。因此,例如从int
到long
的内置隐式演员表;使用long x = 3
,它绝对清楚会发生什么(long
值x
现在是3L
)。
与DateTime.Now.AddTicks(2)
类似,很明显我们希望发生相同的行为,就像我们调用DateTime.Now.AddTicks(2L)
一样。强迫我们添加一个明确的演员模糊不清楚。
由于3L.CompareTo(2)
和long
都有int
种方法,因此CompareTo
不太明确,但实际上并没有任何方法可以禁止它:隐式强制转换可以从int
工作到long
,这样就会发生这种情况。
对于2.CompareTo(3L)
,隐式演员开始变得更加混乱,它会解决。即使把这个例子看作是编写它的人,我也不确定它是否意味着((long)2).CompareTo(3L)
或2.CompareTo((int)3L)
。
当我们考虑多个隐式强制转换和多个具有多个重载的类型的影响时,允许在.
运算符左侧隐式强制转换的影响很快就会导致我们陷入极端情况关于什么隐式演员被称为在哪里被暧昧。
隐式铸造的句法糖将成为语法醋。
因此,使用.
运算符进行隐式转换是有道理的。
你的答案中的代码没有语法错误,因为string Test = iFoo.Trim();
可以通过语言规则有意义地解释,但编译错误,因为根据语言规则它只能意味着"打电话给'Trim()'在' Foo'类型上定义的方法或者修剪(T)'扩展方法,其中' T'是'Foo'或者基本类型' Foo'"。没有这样的方法,所以语法是正确的,但结果是不可能实现的。