在类声明中使用 PARTIAL 修饰符可指示编译器,类定义及其成员(方法、属性等)可能会跨当前应用程序/库中的多个程序文件。默认情况下(不使用 PARTIAL 修饰符时),类的所有成员都应在单个文件中定义,如果它们跨多个文件,则该类的所有 CLASS...END CLASS 定义都需要标记为 PARTIAL:
// file code1.prg
PARTIAL CLASS ClassSpanningInMultipleFiles // 省略 PARTIAL 会导致编译器错误,因为在类型声明中缺少部分修饰符。
METHOD MethodInFile1() AS VOID
END CLASS
// file code2.prg
PARTIAL CLASS ClassSpanningInMultipleFiles
PROPERTY PropertyInFile2() AS LOGIC
GET
RETURN TRUE
END GET
END PROPERTY
END CLASS
请注意,部分类的所有成员必须在同一个程序集中定义。不能使用 PARTIAL 修饰符在不同的程序集/库中定义类的成员。
EXTERN 修饰符告诉编译器某个方法是在外部实现的,因此它在代码本身中没有主体。EXTERN 通常与 DllImport 属性(System.Runtime.InteropServices.DllImportAttribute)一起使用,后者指定了方法的具体实现位置(通常在 Win32 API dll 中)和调用方式。使用该属性时,还需要将方法声明为静态方法:
USING System.Runtime.InteropServices
FUNCTION Start() AS VOID
WinAPICalls.MessageBox(IntPtr.Zero, "通过 EXTERN 方法调用非托管代码", "EXTERN 修饰符示例", 0)
STATIC CLASS WinAPICalls
[DllImport("user32.dll", CharSet := CharSet.Unicode)];
STATIC EXTERN METHOD MessageBox(hWnd AS IntPtr, text AS STRING , caption AS STRING , type AS DWORD ) AS INT
END CLASS
请注意,EXTERN 方法直接返回值是编译器错误,因为它的完整实现是由外部提供的。
方法上的 UNSAFE 修饰符指定其整个主体将在不安全上下文中运行,这意味着它可以使用指向数据的指针并直接操作内存。只有启用编译器选项允许不安全代码(/unsafe)后,才能使用不安全修改器:
FUNCTION Start() AS VOID
? UnsafeMethods.GetByte2of4(0x10203040) // 32 (hex 20)
CLASS UnsafeMethods
UNSAFE STATIC METHOD GetByte2of4(d AS DWORD) AS BYTE
LOCAL p AS BYTE PTR
p := (BYTE PTR) @d //获取直接指向数据的指针
RETURN p[3]
END CLASS
当方法体中只有一小部分涉及指针或其他潜在的不安全操作时,更常见的做法是为其声明一个 BEGIN UNSAFE 块,而不是将整个方法标记为不安全:
CLASS UnsafeMethods
STATIC METHOD GetByte2of4(d AS DWORD) AS BYTE
LOCAL b AS BYTE
? "Begin of unsafe possibly code executing"
BEGIN UNSAFE // 该代码块内的代码使用指针操作
LOCAL p AS BYTE PTR
p := (BYTE PTR) @d // 获取直接指向数据的指针
b := p[3]
END UNSAFE
? "End of unsafe code"
RETURN b
END CLASS
请注意,我们强烈反对编写使用指针的代码(因为.Net 运行时无法验证代码的正确使用,而且会破坏运行应用程序的稳定性),只有在绝对必要的情况下,才需要极其谨慎地使用指针。