编译C#不安全代码

编译C#不安全代码,c#,.net,compiler-construction,unsafe,C#,.net,Compiler Construction,Unsafe,我有一个小C#类,其中包含一些不安全的方法。是否有一种方法可以在C源代码(使用#pragma或其他任何方式)中声明性地为类的源文件上下文指定“/unsafe”选项?我不想为这么小的一个类创建一个单独的程序集,但我也不想为程序集的其余部分(该类目前是其一部分)启用不安全代码。C#有一个unsafe关键字,您必须在不安全代码周围使用,以避免人们意外使用不安全代码。这是我能想到的最好的方法:如果有人能在文件中引入unsafe关键字,他们可以很容易地添加或删除#pragma标记或类似的标记 /unsaf

我有一个小C#类,其中包含一些不安全的方法。是否有一种方法可以在C源代码(使用
#pragma
或其他任何方式)中声明性地为类的源文件上下文指定“/unsafe”选项?我不想为这么小的一个类创建一个单独的程序集,但我也不想为程序集的其余部分(该类目前是其一部分)启用不安全代码。

C#有一个
unsafe
关键字,您必须在不安全代码周围使用,以避免人们意外使用不安全代码。这是我能想到的最好的方法:如果有人能在文件中引入
unsafe
关键字,他们可以很容易地添加或删除
#pragma
标记或类似的标记

/unsafe
编译器标记告诉编译器,您可以接受在此程序集中使用
unsafe
关键字的人,并且您认识到它生成的程序集将被标记为“unsafe”,这可能会阻止它在不完全信任的环境中运行。没有办法让编译器仅将单个类标记为不安全的:人们可以信任您的程序集,也可以不信任您的程序集。

不,这(目前)是不可能的,因为整个程序集都会受到不安全代码的影响

通过在程序集中包含不安全的代码,您告诉CLR程序集可能会做一些不安全的事情,这会改变运行时加载程序集时的行为方式。这里最大的变化是CLR不会尝试验证您的不安全代码,但它也会拒绝加载您的程序集,除非它具有完全信任(例如,您不能作为普通用户一次性加载不安全的程序集)

从技术角度来看,当您使用
/unsafe
选项时,它会导致编译器将以下模块级属性的IL等效项发送到程序集中:

[assembly:SecurityPermission(SkipVerification = true)]
[assembly:UnverifiableCode]

正如您所说,您最好的选择是尽可能将不安全代码隔离到它自己的独立程序集中。程序集中只有一个类这一事实与由于一个不安全的类而使整个程序集充满安全代码相比,其代码味道要小得多。

您需要使用/unsafe编译器开关来编译
unsafe
关键字。这是有道理的,尽管我对互操作代码(WinAPI和COM)的方式感到惊讶被认为比不安全代码更安全,因为互操作不需要“/不安全”选项。互操作可能是“安全”的,因为它已经过手动验证。编写程序集的开发人员不允许对它做任何超出MS明确允许的事情(这也是
封送
类可以“安全地”做不安全事情的原因)@MichaelEdenfield,我想说,单独使用恶意的
IntPtr
参数调用
RtlZeroMemory
会比我的无辜指针操作造成更大的伤害,我必须使用“/safe”。我的理解是,每个方法都是不安全的。不是每个组件。它也没有被宣布为AFAIK。当一个方法被放入不可验证的IL时,它就变得不安全了。@usr到C#,不安全的代码是每个代码块的,编译器允许你在不安全的代码块中做通常是非法的事情。对于运行时,不安全代码发生在标记为包含不安全代码的程序集中。尽管安全代码仍然是安全的,但无法告诉运行时“此程序集的一半是安全的,另一半不是安全的”。例如,即使您从未调用过不安全块,整个程序集都需要完全信任才能加载。您确定已标记程序集吗?这就是我所质疑的。我认为甚至连方法都没有在二进制文件中标记。@usr我的答案可能过于简单了,我会修正它。在C#中,除了可以将代码块标记为
不安全
,还可以将整个
标记为
不安全
。但这可能相当于将该类中的所有“块”标记为不安全的。使用/unsafe选项只能抑制显式使用unsafe关键字的类/方法的编译时错误。它不会使未以这种方式声明的代码在任何方面都不安全。因此,正如@StriplingWarrior所建议的,在生成的程序集中是否有一个特殊的标志?