【问题标题】:What is the difference between "this ref" and "ref this" when talking about C# 7.2 ref extension methods?在谈论 C# 7.2 ref 扩展方法时,“this ref”和“ref this”有什么区别?
【发布时间】:2019-12-23 03:50:03
【问题描述】:

考虑以下扩展方法:

public static void Toggle(this ref bool @bool) => @bool = !@bool;

public static void Toggle2(ref this bool @bool) => @bool = !@bool;

这些只是切换一个 ref 布尔变量值。测试:

class Foo
{
    private bool _flag;
    public void DoWork()
    {
        _flag.Toggle();
        Console.WriteLine(_flag);
        _flag.Toggle2();
        Console.WriteLine(_flag);
    }
}

我们得到:

True
False

问题:选择一种语法或另一种语法有什么隐藏的区别吗?

【问题讨论】:

    标签: c# extension-methods ref c#-7.2


    【解决方案1】:

    不,它们完全相同,就像(现在)您可以使用 $@@$ 编写插入的逐字字符串文字。

    【讨论】:

    • 还有一件事要问。声明静态异步方法时,是否有区别:public static async... vs public async static?
    • 根据语言规范,它们完全相同,但根据 Roslyn =)
    • @taquion 你能解释一下吗?似乎您可能在暗示某种经过充分讨论的争议或其他(尽管您的信息是一个需要分析的微小“信号”)。无论如何,您能为我这样的非 Roslyn 专家详细说明吗?
    【解决方案2】:

    没有区别。这些被称为修饰符,它们在规范中的顺序是未定义

    您可以在此处阅读C# Language Specification 中有关方法参数的部分:

    https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#method-parameters

    它列出了不同的选项并定义了它们如何交互和混合,但没有说明您必须使用什么顺序。

    【讨论】:

    • 根据语言规范,它们完全相同,但根据 Roslyn =)
    【解决方案3】:

    尽管根据语言规范它们完全相同。我发现了一个差异,它必须对编译器做更多的事情,这可能是一个编译器错误。重现此问题的设置是使用 Visual Studio 2019。该错误可能在其他编译器版本中,我真的没有对此进行更多研究。

    如果您的语言级别为 7.2 或更高,则两种语法的工作方式相同。但是,如果您的项目使用语言级别 7.0 或 7.1,那么将编译以下代码:

    struct S {}
    
    static class Extensions
    {
        static void M(this ref S s) {}
    }
    

    但是如果我们像这里这样改变修饰符的顺序:

    static class Extensions
    {
        static void M(ref this S s) {}
    }
    

    您将收到以下编译器错误消息:

    错误 CS8107:功能“引用扩展方法”在 C# 7.0 中不可用。请使用 7.2 或更高版本的语言。

    奇怪的是虽然static void M(this ref S s)可以编译,但是没有办法将方法作为S的扩展方法来消费:

    s.M() //error CS8107 here

    但是您可以使用传统的静态语法调用该方法:

    Extensions.M(ref s)

    因此,尽管语言规范没有区别,但对于那些使用 Roslyn 编译器的人来说,最好使用 this ref 而不是 ref this,因为只要存在错误,这将向后兼容 7.0 和 7.1那里海事组织

    我向here 报告了缺少结构的引用扩展方法的信息,而其他一些人向Roslyn 报告了这个问题。

    我没有将此答案标记为答案,因为我认为 @Jon Skeet 和 @Joel Coehoorn 的答案在语言方面更准确。但我认为无论如何这都是有用的信息

    【讨论】:

    • "...最好使用this ref 而不是ref this"... 嗯,真的吗?仅基于阅读您信息中的优秀信息,我会倾向于相反的方式。对我来说,“[无法] [无法]将该方法用作扩展方法”似乎比“向后兼容 7.0 和 7.1”更严重。前者既是语言存在实体领域的错误和限制,编译器修订打嗝似乎是行政死水?也许因为 C# 如此稳定可靠,我只是假设每个人都将旧版本留在了死里......
    猜你喜欢
    • 1970-01-01
    • 2016-10-07
    • 1970-01-01
    • 1970-01-01
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    相关资源
    最近更新 更多