首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带字符串插值的重载字符串方法

带字符串插值的重载字符串方法
EN

Stack Overflow用户
提问于 2016-03-03 11:17:27
回答 4查看 1.3K关注 0票数 14

为什么字符串插值喜欢使用string而不是IFormattable的方法过载

设想如下:

代码语言:javascript
复制
static class Log {
    static void Debug(string message);
    static void Debug(IFormattable message);
    static bool IsDebugEnabled { get; }
}

我有一些ToString()很贵的东西。在此之前,我做了以下工作:

代码语言:javascript
复制
if (Log.IsDebugEnabled) Log.Debug(string.Format("Message {0}", expensiveObject));

现在,我希望IsDebugEnabled逻辑在Debug(IFormattable)中,并且只在必要时对消息中的对象调用ToString()。

代码语言:javascript
复制
Log.Debug($"Message {expensiveObject}");

然而,这就调用了Debug(string)重载。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-03-03 11:27:21

这是一个罗斯林团队深思熟虑的决定

我们通常认为,对于执行不同任务的方法,库大多会使用不同的API名称编写。因此,FormattableString和String之间的重载解决方案差异并不重要,所以字符串可能也会赢。因此,我们应该坚持一个简单的原则,即插值字符串就是字符串。故事到此结束。

链接中对此有更多的讨论,但结果是他们希望您使用不同的方法名称。

一些库API确实希望消费者使用FormattableString,因为它更安全或更快。接受字符串的API和使用FormattableString的API实际上做了不同的事情,因此不应该在相同的名称上重载。

票数 11
EN

Stack Overflow用户

发布于 2016-08-19 09:14:22

当你意识到你为什么不能这么做的时候,我只想指出,事实上你可以做到这一点。

您只需要欺骗编译器,使它更喜欢FormattableString重载。我已经在这里详细解释过了:https://robertengdahl.blogspot.com/2016/08/how-to-overload-string-and.html

下面是测试代码:

代码语言:javascript
复制
public class StringIfNotFormattableStringAdapterTest
{
    public interface IStringOrFormattableStringOverload
    {
        void Overload(StringIfNotFormattableStringAdapter s);
        void Overload(FormattableString s);
    }

    private readonly IStringOrFormattableStringOverload _stringOrFormattableStringOverload =
        Substitute.For<IStringOrFormattableStringOverload>();

    public interface IStringOrFormattableStringNoOverload
    {
        void NoOverload(StringIfNotFormattableStringAdapter s);
    }

    private readonly IStringOrFormattableStringNoOverload _noOverload =
        Substitute.For<IStringOrFormattableStringNoOverload>();

    [Fact]
    public void A_Literal_String_Interpolation_Hits_FormattableString_Overload()
    {
        _stringOrFormattableStringOverload.Overload($"formattable string");
        _stringOrFormattableStringOverload.Received().Overload(Arg.Any<FormattableString>());
    }

    [Fact]
    public void A_String_Hits_StringIfNotFormattableStringAdapter_Overload()
    {
        _stringOrFormattableStringOverload.Overload("plain string");
        _stringOrFormattableStringOverload.Received().Overload(Arg.Any<StringIfNotFormattableStringAdapter>());
    }

    [Fact]
    public void An_Explicit_FormattableString_Detects_Missing_FormattableString_Overload()
    {
        Assert.Throws<InvalidOperationException>(
            () => _noOverload.NoOverload((FormattableString) $"this is not allowed"));
    }
}

下面是使这一工作有效的代码:

代码语言:javascript
复制
public class StringIfNotFormattableStringAdapter
{
    public string String { get; }

    public StringIfNotFormattableStringAdapter(string s)
    {
        String = s;
    }

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

    public static implicit operator StringIfNotFormattableStringAdapter(FormattableString fs)
    {
        throw new InvalidOperationException(
            "Missing FormattableString overload of method taking this type as argument");
    }
}
票数 11
EN

Stack Overflow用户

发布于 2020-02-26 12:16:46

您不能强迫编译器在字符串上选择IFormattable/FormattableString,但是可以使它选择IFormattable/FormattableString而不是Object:

代码语言:javascript
复制
static class Log
{
    static void Debug(object message);
    static void Debug(IFormattable message);
    static void Debug(FormattableString message);
    static bool IsDebugEnabled { get; }
}

该解决方案的成本是接受对象的方法中的一个额外的ToString()-call。(对于FormattableString来说,额外的重载并不是必要的,但是可以简化使用内插条纹的位置的查找)

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

https://stackoverflow.com/questions/35770713

复制
相关文章

相似问题

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