如何避免类和方法的可访问性不一致导致的编译错误?
Posted
技术标签:
【中文标题】如何避免类和方法的可访问性不一致导致的编译错误?【英文标题】:How to avoid the compilation error with inconsistent accessibility of class and methods? 【发布时间】:2019-09-26 00:24:28 【问题描述】:我对 Autodesk 装配体进行了反思,发现如下:
请注意,对于PressurePipeNetwork
类,它是public
,并且有一个方法AddLinePipe
,它也是一个public
。但是,AddLinePipe
、PressurePartSize
的参数之一是internal
。
通常我们将无法在 .Net 中使用这样的代码进行编译(并且我们会得到“Inconsistent Accessibility”类型的编译错误)。但不知何故,这个大会侥幸逃脱了。
我已经检查过了,程序集中只有一个PressurePartSize
。
我不太确定何时有人说它不能完成。 欧特克已经做到了;我得到了程序集!
不仅如此,人们还可以以某种方式使用 C# 中的库,but with the error message
Autodesk.Civil.DatabaseServices.Styles.PressurePartSize 正在显示 由于保护级别而无法访问的错误。
怎么做? 我愿意使用任何语言来实现这一点,而不仅仅是 C#。或.Net
【问题讨论】:
我不知道。但几乎没有迹象表明这个库是用 C# 编写的。该库的开发人员可以使用不同的语言,使用对这些事情不那么严格的不同编译器。 (或者,也许很久以前在 C# 中使用了一个古老的 C# 编译器,该编译器还没有那种可访问性检查;我真的不知道,我只是边走边写。;-) ) 你做不到。时期。另一个不同的问题是反编译的代码是什么意思,如果两个 PressurePartSize 类型相同,它们是如何实现的,但是使用今天的 C# 编译器,你无法做到。 值得注意的是,PressurePipeNetwork
的唯一构造函数是内部的。
我也质疑这个反编译的有效性,看起来 Telerik 反编译器在这个代码上到处都是,你确定它被正确反编译,可读的部分吗?当然,它令人讨厌的原因当然可能是代码不是有效的 C#,它试图将其硬塞到 C# 语法中,但没有成功。
这不是 C# 代码,它是用 C++/CLI 编写的。 PressurePartSize 很可能是原生 C++ 类。 C++/CLI 编译器为此类发出元数据定义,但它不可访问。只要调用是从 C++/CLI 代码进行的,就不是问题。这个反编译器死在它上面并不是很不寻常。 Reflector 在此类代码上做得更好,但没有 .NET 反编译器会反编译本机代码。
【参考方案1】:
只是一个建议。可能有两个PressurePartSize
类:一个公共的和一个内部的。图片看不清楚。
类似这样的:
namespace SampleLib
using SampleLib.Internal;
//using SampleLib.Public;
public class PublicClass
public unsafe void PublicMethod(InternalClass internalClass)
namespace SampleLib.Internal
internal sealed class InternalClass
namespace SampleLib.Public
public sealed class InternalClass
错误 CS0051 可访问性不一致:参数类型“InternalClass”的可访问性低于方法“PublicClass.PublicMethod(InternalClass)”
但是
namespace SampleLib
//using SampleLib.Internal;
using SampleLib.Public;
public class PublicClass
public unsafe void PublicMethod(InternalClass internalClass)
namespace SampleLib.Internal
internal sealed class InternalClass
namespace SampleLib.Public
public sealed class InternalClass
没问题。
更新
只有一个 PressurePartSize,请看更新后的问题。
他们一开始似乎有Autodesk.Civil.DatabaseServices.Styles.PressurePartSize
public。然后他们用public unsafe ObjectId AddLinePipe(LineSegment3d line, PressurePartSize partSize)
创建了一个库并构建了它。然后他们将Autodesk.Civil.DatabaseServices.Styles.PressurePartSize
改为internal,但没有重建调用库。但是 JIT 编译器会在运行时检查可访问性。这就是exception you mentioned 的原因。
【讨论】:
只有一个PressurePartSize
,见更新问题【参考方案2】:
这不能在 C# 中完成。不过,.NET 虚拟机比 C# 更宽松。 许多 C# 没有公开的特性。
在 IL 级别,您可以调用非公共方法就好了。您也可以使用反射发射使用运行时代码生成来做到这一点。这对于创建快速序列化程序非常有用。
JIT 还能够编译无法验证甚至不正确的 IL。结果未完全定义。
这个程序集是如何创建的?我的第一个想法是,这是 IL 链接器工具的结果。 .NET 程序集可以进行后处理以合并或优化它们。这也可能是混淆工具的结果(尤其是无法反编译的方法)。
看起来该工具有一个错误,因为它肯定不是有意创建一个通常不可调用的公共方法。
如果您想对此进行试验,您可以将任何程序集反编译为 IL,对其进行编辑和编译。 IL 可以往返任何我相信的东西。
【讨论】:
以上是关于如何避免类和方法的可访问性不一致导致的编译错误?的主要内容,如果未能解决你的问题,请参考以下文章
c#错误不一致的可访问性:参数类型'HRDMSV1.User'比方法更难访问