我一直在研究一个相当大的包装器,为了理智,我使用partial修饰器分割多个文件.包装器大量使用不安全的指针,因此我选择在类级别上简单地声明它以覆盖其中的所有内容.
public static unsafe partial class Ruby { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static VALUE CLASS_OF(VALUE obj) => ((RBasic*) obj)->klass; }
在另一个文件中:
public static unsafe partial class Ruby { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void* DATA_PTR(VALUE obj) => ((RData*) obj)->data; }
每个部分声明都需要unsafe修饰符,以便“允许”和编译不安全的代码,这是可以理解的,我希望部分类的类声明需要完全匹配.
但是使用这个逻辑,我也被允许有另一个不安全的文件:
[SuppressUnmanagedCodeSecurity] public static partial class Ruby { [DllImport(RUBY_LIBRARY,CallingConvention = CallingConvention.Cdecl)] public static extern VALUE rb_ivar_get(VALUE obj,ID name); }
在这里,我不使用unsafe修饰符,它是完全可以接受的(显然这个文件中没有不安全的代码).
我是什么希望得到澄清为什么这允许.每个分类的类声明不应该完全匹配吗?不允许更改/排除任何其他类修饰符,例如私有,公共,抽象等,所以为什么这是不安全的.在我看来,这种行为似乎不一致.我的猜测是,它在不同的情况下由编译器在不同的上下文中运行,但这只是我的猜想,并且希望有人比我更了解这个可能会有所启发.
解决方法
public abstract partial class Foo { } partial class Foo { }
Foo将表示一个抽象类,因为它的一个部分被声明为abstract.有关部分类的类修饰符的规则可以在规范的10.2.2节中找到.这是与不安全的部分类相关的文本:
When the unsafe modifier is used on a partial type declaration,only that particular part is considered an unsafe context (§18.1).
当密封或抽象应用于部分类时,该类的所有部分都被认为是密封的或抽象的.但它不能同时存在.
实际上,可访问性是partials上唯一必须在所有部分之间保持一致的类修饰符,但不需要在所有部分中设置.
When a partial type declaration includes an accessibility specification (the public,protected,internal,and private modifiers) it must agree with all other parts that include an accessibility specification. If no part of a partial type includes an accessibility specification,the type is given the appropriate default accessibility (§3.5.1).
这基本上归结为不允许声明公共部分类Bar和内部部分类Bar,因为部件之间的可访问性变得不一致.声明没有可访问性的其他部分将默认为已声明的可访问性,或默认值为规范3.5.1节中规定的规则.
注意:我引用的规范部分来自Visual Studio 2017附带的规范版本.
ECMA-334参考文献如下:
23.2:
When the unsafe modifier is used on a partial type declaration (§15.2.7),only that particular part is
considered an unsafe context.
15.2.2.1:
When a partial type declaration (§15.2.7) includes an accessibility specification (via the public,
protected,and private modifiers),that specification shall agree with all other parts that
include an accessibility specification. If no part of a partial type includes an accessibility specification,the
type is given the appropriate default accessibility (§8.5.2).
15.2.2.2和15.2.2.3有关于抽象和密封修饰符的规则.