什么是’无法validation的代码’,为什么它不好?

我正在设计一个帮助方法,为我延迟加载某些对象,调用它看起来像这样:

public override EDC2_ORM.Customer Customer { get { return LazyLoader.Get( CustomerId, _customerDao, ()=>base.Customer, (x)=>Customer = x); } set { base.Customer = value; } } 

当我编译这段代码时,我得到以下警告:

警告5通过匿名方法,lambda表达式,查询表达式或迭代器中的’base’关键字访问成员’EDC2_ORM.Billing.Contract.Site’会导致无法validation的代码。 考虑将访问权限移动到包含类型的帮助程序方法。

这里的投诉到底是什么,为什么我做得不好?

虚拟方法的“base.Foo”将对方法“Foo”的父定义进行非虚拟调用。 从CLR 2.0开始,CLR决定对虚拟方法进行非虚拟调用可能是一个潜在的安全漏洞,并限制了可以使用的场景。 他们将其限制为在同一类层次结构中对虚拟方法进行非虚拟调用。

Lambda表达式在这个过程中发生了变化。 Lambda表达式通常会在引擎盖下生成一个闭包,这是一个完全独立的类。 因此代码“base.Foo”最终将成为一个全新类中的表达式。 这会在CLR中创建validationexception。 因此C#发出警告。

附注:等效代码适用于VB。 在VB中,对虚拟方法进行非虚拟调用,将在原始类中生成方法存根。 非虚拟呼叫将在此方法中执行。 “base.Foo”将被重定向到“StubBaseFoo”(生成的名称不同)。

我怀疑问题在于你基本上是在说,“我不想使用客户最常用的实现 – 我想使用这个特定的实现” – 你通常无法做到这一点。 您可以在派生类中执行此操作,并且有充分的理由,但是从其他类型开始,您将违反封装。

现在,当您使用匿名方法,lambda表达式,查询表达式(基本上使用lambda表达式)或迭代器块时,编译器有时必须在幕后为您创建一个新类。 有时它可以为lambda表达式创建一个相同类型的新方法,但它取决于上下文。 基本上,如果在lambda表达式中捕获任何局部变量,那么需要一个新类(或者实际上是多个类,具体取决于范围 – 它可能会变得令人讨厌)。 如果lambda表达式仅捕获this引用,则可以为lambda表达式逻辑创建新的实例方法。 如果没有捕获任何内容,静态方法就可以了。

因此,虽然C#编译器知道你真的没有违反封装,但CLR却没有 – 所以它会怀疑地对待代码。 如果您在完全信任下运行,那可能不是问题,但在其他信任级别(我不知道详细信息),您的代码将不被允许运行。

这有帮助吗?

从这里复制/粘贴:

Codesta:C#/ CLR有2种代码,安全且不安全。 它试图提供什么以及它如何影响虚拟机? Peter Hallam:对于C#来说,这些术语是安全且不安全的。 CLR使用可validation且无法validation的术语。

运行可validation代码时,CLR可以实施安全策略; CLR可以防止可validation的代码执行它无权执行的操作。 例如,当运行从Internet下载的潜在恶意代码时,CLR将只运行可validation的代码,并确保不受信任的代码不会访问它无权访问的任何内容。

使用标准C样式指针会产生无法validation的代码。 CLR原生支持C风格指针。 一旦获得了C样式指针,就可以读取或写入进程中的任何内存字节,因此运行时无法强制执行安全策略。 实际上它可以,但性能损失将使其不切实际。

现在,这并没有完全回答你的问题(即为什么这是现在无法validation的代码),但至少它解释了“无法validation”是“不安全”的CLR术语。 我假设匿名方法和基类在内部产生一些时髦的指针魔法。

顺便说一句:我认为代码片段与警告消息不匹配。 代码是在讨论客户,警告是关于结算。 是否可以发布生成警告的执行代码? 也许您在该代码中还有其他内容可以更好地解释您收到警告的原因。