在谈论 C# 7.2 ref 扩展方法时,“this ref”和“ref this”有啥区别?
Posted
技术标签:
【中文标题】在谈论 C# 7.2 ref 扩展方法时,“this ref”和“ref this”有啥区别?【英文标题】: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
问题:选择一种语法或另一种语法有什么隐藏的区别吗?
【问题讨论】:
【参考方案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# 如此稳定可靠,我只是假设每个人都将旧版本留在了死里......以上是关于在谈论 C# 7.2 ref 扩展方法时,“this ref”和“ref this”有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章