在谈论 C# 7.2 引用扩展方法时,"this ref" 和 "ref this" 有什么区别?
What is the difference between "this ref" and "ref this" when talking about C# 7.2 ref extension methods?
考虑以下扩展方法:
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# Language Specification 中关于方法参数的部分:
它列出了不同的选项并定义了它们如何相互作用和混合,但没有说明必须使用的顺序。
尽管根据语言规范,它们完全相同。我发现了一个必须对编译器做更多事情的差异,这可能是一个编译器错误。重现此问题的设置是 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) {}
}
您将收到以下编译器错误消息:
error CS8107: Feature 'ref extension methods' is not available in C# 7.0. Please use language version 7.2 or greater.
奇怪的是,虽然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 the lack of information about ref extensions methods for structs, and some other guy reported to Roslyn 这个问题。
我没有将这个答案标记为 THE answer,因为我认为 @Jon Skeet 和 @Joel Coehoorn 的那些在语言方面更准确。但我认为这无论如何都是有用的信息
考虑以下扩展方法:
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# Language Specification 中关于方法参数的部分:
它列出了不同的选项并定义了它们如何相互作用和混合,但没有说明必须使用的顺序。
尽管根据语言规范,它们完全相同。我发现了一个必须对编译器做更多事情的差异,这可能是一个编译器错误。重现此问题的设置是 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) {}
}
您将收到以下编译器错误消息:
error CS8107: Feature 'ref extension methods' is not available in C# 7.0. Please use language version 7.2 or greater.
奇怪的是,虽然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 the lack of information about ref extensions methods for structs, and some other guy reported to Roslyn 这个问题。
我没有将这个答案标记为 THE answer,因为我认为 @Jon Skeet 和 @Joel Coehoorn 的那些在语言方面更准确。但我认为这无论如何都是有用的信息