如何定义允许方法调用的隐式强制转换

本文关键字:转换 调用 何定义 定义 许方法 方法 | 更新日期: 2023-09-27 18:09:59

假设有一个结构体,允许隐式强制转换为某种类型,如'string',如下所示:

public struct Foo
{
    public string Value;
    public static implicit operator string(Foo i)
    {
        return i.Value;
    }
}

iFooFoo的一个实例。基于这个定义,赋值与随后的方法调用,如

string Test = iFoo;
Test = Test.Trim();

在语法上是正确的,而像

这样的压缩调用
string Test = iFoo.Trim();

不是。具体原因是什么?期望的行为(在Foo的实例上调用string的方法的可能性)是否可以实现-当然仅通过隐式转换的方式?如果不是,第二段代码语法错误的原因是什么?

如何定义允许方法调用的隐式强制转换

不,方法调用将使用不同的规则完成,并且不涉及像那样的强制转换。如果没有:

你将无法做你想做的事。
  1. 在你自己的类型之上实现所有你需要/想要的方法
  2. 实现你需要/想要的所有方法作为你的类型的扩展方法

隐式强制转换允许两种情况:

好吧,这听起来有点同义,但让我们一次看一个,先看强制转换。

由于强制转换,您可以:

string Test = ((string)iFoo).Trim();

这是有效的,因为表达式((string)iFoo)有一个定义的工作方式(因为强制转换),当你把表达式((string)iFoo).Trim()分解成组成它的表达式时,它们都是语法和有意义的,并且有定义的行为。

现在,隐含的部分是,作为语法糖,我们可以省略在某些情况下进行转换的(string)部分。这通常是因为所涉及的"扩展"转换是如此明显,强制转换会(或至少有争议)分散程序员的注意力,而不是让他们清楚地了解事情。因此,例如从intlong的内置隐式强制转换;对于long x = 3,它绝对清楚会发生什么(long的值x现在是3L)。

同样与DateTime.Now.AddTicks(2),很明显,我们希望同样的行为发生,如果我们调用DateTime.Now.AddTicks(2L)。强制我们添加显式强制转换,其模糊程度大于它的清晰程度。

对于3L.CompareTo(2),它变得不那么清楚,因为longint都有CompareTo方法,但实际上没有任何方法可以禁止它:从intlong的隐式强制转换工作,所以这就是这里将要发生的事情。

2.CompareTo(3L)中,隐式强制类型转换开始变得更加混乱,而不是解决问题。即使我自己作为作者来看这个例子,我也不确定它是指((long)2).CompareTo(3L)还是2.CompareTo((int)3L)

当我们考虑多个隐式强制转换的影响以及对多个重载的多个类型的影响时,允许在.操作符左侧进行隐式强制转换的影响可能很快导致我们对在哪里调用哪些隐式强制转换非常不明确。

隐式强制转换的语法糖将变成语法醋。

因此,没有使用.操作符进行隐式强制转换是有意义的。

您的答案中的代码没有语法错误,因为string Test = iFoo.Trim();可以通过语言的规则有意义地解释,但是编译器错误,因为通过语言的规则,它只能意味着"调用'Trim()'方法定义在类型'Foo'或'Trim(T)'扩展方法,其中'T'是'Foo'或'Foo'的基本类型"。没有这样的方法,所以语法是正确的,但结果是不可能实现的。