使用"部分"时为什么类级"不安全"修饰符不一致?

For*_*er0 6 c# unsafe

我已经注意到unsafe在类级别上对部分类使用修饰符时的某种行为,我希望得到一些澄清.

我一直在研究一个相当大的包装器,为了理智,我使用partial修饰符分割多个文件.包装器大量使用unsafe指针,因此我选择在类级别上简单地声明它以覆盖其中的所有内容.

public static unsafe partial class Ruby
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static VALUE CLASS_OF(VALUE obj) => ((RBasic*) obj)->klass;
}
Run Code Online (Sandbox Code Playgroud)

在另一个文件中:

public static unsafe partial class Ruby
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void* DATA_PTR(VALUE obj) => ((RData*) obj)->data;
}
Run Code Online (Sandbox Code Playgroud)

unsafe修改需要每个部分的声明,以使不安全的代码被"允许"和编译,这是可以理解的,我希望,对于部分类的类声明将需要完全匹配.

但是使用那个逻辑,我也被允许有另一个不是的文件unsafe:

[SuppressUnmanagedCodeSecurity]
public static partial class Ruby
{
    [DllImport(RUBY_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
    public static extern VALUE rb_ivar_get(VALUE obj, ID name);
}
Run Code Online (Sandbox Code Playgroud)

在这里,我不使用unsafe修饰符,它是完全可以接受的(显然在这个文件中没有不安全的代码).

我是什么希望得到澄清为什么这允许.每个分类的类声明不应该完全匹配吗?改变/不包括任何其他类改性剂是不允许的,例如private,public,abstract等等,所以这是为什么好吗用unsafe.在我看来,这种行为似乎不一致.我的猜测是,它在不同的情况下由编译器在不同的上下文中运行,但这只是我的猜想,并且希望有人比我更了解这个可能会有所启发.

Jon*_*ase 11

关于需要一致性的修饰语的断言有点过时了.例如,这是完全有效的:

public abstract partial class Foo { }

partial class Foo { }
Run Code Online (Sandbox Code Playgroud)

Foo将代表一个抽象类,因为它的一个部分被声明为抽象.有关部分类的类修饰符的规则可以在规范的10.2.2节中找到.这是与unsafe部分类相关的文本:

当在部分类型声明上使用unsafe修饰符时,只将该特定部分视为不安全的上下文(第18.1节).

sealedabstract应用于部分类时,该类的所有部分都被视为sealedabstract.但它不能同时存在.

实际上,可访问性是partials上唯一必须在所有部分之间保持一致的类修饰符,但不需要在所有部分中设置.

当部分类型声明包含可访问性规范(public,protected,internal和private修饰符)时,它必须与包含可访问性规范的所有其他部分一致.如果部分类型的任何部分都不包含可访问性规范,则为该类型提供适当的默认可访问性(第3.5.1节).

这基本上归结为不允许声明a public partial class Bar和a两者internal partial class Bar,因为部件之间的可访问性变得不一致.声明没有可访问性的其他部分将默认为已声明的可访问性,或默认值为规范3.5.1节中规定的规则.

注意:我引用的规范部分来自Visual Studio 2017附带的规范版本.

ECMA-334参考如下:

23.2:

当在部分类型声明(第15.2.7节)上使用unsafe修饰符时,只将该特定部分视为不安全的上下文.

15.2.2.1:

当部分类型声明(第15.2.7节)包含可访问性规范(通过public,protected,internal和private修饰符)时,该规范应与包含可访问性规范的所有其他部分一致.如果部分类型的任何部分都不包含可访问性规范,则为该类型提供适当的默认可访问性(第8.5.2节).

15.2.2.2和15.2.2.3有关于abstractsealed修饰语的规则.

  • @ M.Hassan完成. (2认同)