C# 方法重载解析和用户定义的隐式转换

10

我尝试查找有关存在用户定义的隐式类型转换以及转换优先级的情况下,方法重载解析的信息。

以下代码:

class Value
{
    private readonly int _value;
    public Value(int val)
    {
        _value = val;
    }

    public static implicit operator int(Value value)
    {
        return value._value;
    }

    public static implicit operator Value(int value)
    {
        return new Value(value);
    }
}

class Program
{
    static void ProcessValue(double value)
    {
        Console.WriteLine("Process double");
    }

    static void ProcessValue(Value value)
    {
        Console.WriteLine("Process Value");
    }

    static void Main(string[] args)
    {
        ProcessValue(new Value(10));
        ProcessValue(10);
        Console.ReadLine();
    }
}

产生输出:

Process Value
Process Value

看起来编译器选择了用户定义的转换而不是从int到double的内置隐式转换(由于这个页面 https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/implicit-numeric-conversions-table 上的信息,内置转换是隐式的)。

我试图在规范中找到关于这方面的内容,但没有成功。

为什么编译器选择了 ProcessValue(Value value) 而不是 ProcessValue(double value)


它不会进行两次转换,因此它不会将其转换为double,然后再将double转换为Value,而是寻找直接的强制转换/转换。 - Lasse V. Karlsen
2
@LasseVågsætherKarlsen:OP并不希望它执行两次转换。他们只期望从'int'转换为'double'(或者可能将其视为模棱两可)。 - Jon Skeet
1
目前来看,这对我来说看起来像是编译器或规范上的错误。我认为它应该是模棱两可的。 - Jon Skeet
@Jon Skeet 或者内置转换应该在可能的转换列表中首先出现。现在看起来它能够通过添加用户定义的转换来改变现有代码的语义。 - Daniel Vlasenko
1
@DanielVlasenko:噢,你绝对可以通过添加用户定义的转换来改变现有代码的语义。这很容易举例说明。但至少在规范中应该能够解释清楚这一点... - Jon Skeet
1个回答

4

1
只是为了给OP提供一些额外的上下文:10int 类型,而 10.0double 类型。 - Stefan
3
现在我仔细阅读了原帖的问题,我认为他已经知道这一点。我会保留这个答案一段时间,以防其他人回答相同的问题。 - Leonardo Herrera
“优先级”仅在运算符重载解析中使用,而此处未使用。在这种情况下,两种方法都适用,“更好的函数成员”的规则应该适用。如果意图是让用户定义的运算符实现在这里“获胜”,则应在“更好的转换目标”中显示。我真的不认为规范目前处理这种情况。 - Jon Skeet
哎呀,你说得对。但是阅读文档后,我认为它通过说明隐式转换的参数很重要来处理这个问题,并且在决定更具体的参数类型时更好(7.5.3.2)。 - Leonardo Herrera
是的,我们必须选择要使用哪种转换,并且我们看到关于用户定义转换的这个句子,我们可以猜测它也适用于方法重载决策。但。它仍然是关于转换运算符的解决。int->double不是我理解的转换运算符,它是内置转换,而int->Value是通过转换运算符重载定义的用户定义转换。如果int->double按规范是一个转换运算符,那么这就是答案。 - Daniel Vlasenko
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接