请考虑以下扩展方法:
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
问题:选择一种或另一种语法有任何隐藏的区别吗?
答案 0 :(得分:4)
不是,它们是完全一样的,就像(现在)您可以使用$@
或@$
编写内插逐字字符串文字一样。
答案 1 :(得分:1)
没有区别。这些被称为修饰符,其在规范中的顺序为未定义。
您可以在C# Language Specification中阅读有关方法参数的部分:
它列出了不同的选项,并定义了它们如何交互和混合,但没有说明必须使用的顺序。
答案 2 :(得分:0)
尽管根据语言规范它们完全相同。我发现必须对编译器做更多的改变,这可能是编译器错误。重现此设置是在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向后兼容IMO就是这个错误了
我报告here缺少有关struct的ref扩展方法的信息,而另一些人则向Roslyn报告了该问题。
我没有将此答案标记为答案,因为我认为@Jon Skeet和@Joel Coehoorn的语言在语言方面更为准确。但是我仍然认为这是有用的信息