首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有隐式转换的过载解析

具有隐式转换的过载解析
EN

Stack Overflow用户
提问于 2020-03-20 16:41:17
回答 1查看 316关注 0票数 6

我基本上希望string/FormattableString有两个单独的重载(背景是,我希望促使人们使用字符串常量来处理日志消息,并通过结构化日志记录传递参数,而不是通过日志消息来简化分析。因此,FormattableString日志记录方法将被淘汰)。

现在,由于编译器的工作方式,您不能直接重载方法,因为在传递字符串之前,FormattableString会转移到字符串中。但是,有一个定义隐式重载的包装器结构是可行的:

代码语言:javascript
复制
public struct StringIfNotFormattableStringAdapter
{
    public string StringValue { get; }

    private StringIfNotFormattableStringAdapter(string s)
    {
        StringValue = s;
    }

    public static implicit operator StringIfNotFormattableStringAdapter(string s)
    {
        return new StringIfNotFormattableStringAdapter(s);
    }

    public static implicit operator StringIfNotFormattableStringAdapter(FormattableString fs)
    {
        throw new InvalidOperationException("This only exists to allow correct overload resolution. " +
                                            "This should never be called since the FormattableString overload should be preferred to this.");
    }
}

public static class Test
{
    public static void Log(StringIfNotFormattableStringAdapter msg)
    {
    }

    public static void Log(FormattableString msg)
    {
    }

    public static void Foo() 
    {
         Log("Hello"); // resolves to StringIfNotFormattableStringAdapter overload
         Log($"Hello"); // resolves to FormattableString overload 
    } 

}

到目前一切尚好。

我不明白的是:为什么要移除

代码语言:javascript
复制
implicit operator StringIfNotFormattableStringAdapter(FormattableString fs)

导致调用Log($"Hello")变得模糊?

Test.Log(StringIfNotFormattableStringAdapter)‘和’Test.Log(FormattableString)‘’

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-23 03:24:09

根据C#规范,内插字符串,有一个内插字符串到FormattableString的隐式转换

interpolated_string_expression被归类为值。如果立即使用隐式内插字符串转换( System.IFormattable )将其转换为System.FormattableStringSystem.FormattableString,则内插字符串表达式具有该类型。否则,它具有string类型。

在所提供的代码中,还可以将string转换为StringIfNotFormattableStringAdapter

方法调用

代码语言:javascript
复制
Log($"Hello");

可以解析为两个Log方法,因为内插字符串表达式$"Hello"可以是:

  • 隐式转换为FormattableString作为内插字符串;
  • 隐式转换为StringIfNotFormattableStringAdapter作为string

在这里,编译器出现了一种矛盾,需要额外的规则来解决这种歧义。要解决歧义编译器使用C#规范、更好的转换目标(转到第164页的底部)中描述的规则。规则规定:

给定两种不同类型的T1T2,如果不存在从T2T1的隐式转换,则T1是比T2更好的转换目标,并且至少有以下一种情况:

  • T1T2的隐式转换存在
  • (其他规则对我们的情况不重要)

在提供的代码中,FormattableStringStringIfNotFormattableStringAdapter更好的转换,因为

  • 没有从StringIfNotFormattableStringAdapterFormattableString的隐式转换。

  • 存在从FormattableStringStringIfNotFormattableStringAdapter的隐式转换。

因此,编译器倾向于将插值的字符串$"Hello"转换为FormattableString,然后调用方法Log(FormattableString)

为什么要删除 隐式运算符StringIfNotFormattableStringAdapter(FormattableString fs) 导致调用Log($"Hello")变得模糊?

因为当您删除此操作符时,第二条规则(“存在从FormattableStringStringIfNotFormattableStringAdapter的隐式转换”)中断,现在编译器无法定义更好的转换目标。这会导致编译器出现歧义,并出现编译错误。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60778208

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档