Vb.net 访问类库中的mustoverride属性时发生AccessViolationException

Vb.net 访问类库中的mustoverride属性时发生AccessViolationException,vb.net,inheritance,dll,access-violation,Vb.net,Inheritance,Dll,Access Violation,这有点复杂,但我会尽量解释清楚 我有一个通用代码组件类库;我还尝试创建一些常见的ConfigurationHandler基类,以简化创建自定义配置节、集合和元素的过程 我最后得到的是: ConfigurationSectionBase类是泛型的,将tconfementCollection作为{ConfigurationElementCollection,New}作为类型约束 此ConfigurationSectionBase类包含一个Public MustOverride属性集合作为tconfe

这有点复杂,但我会尽量解释清楚

我有一个通用代码组件类库;我还尝试创建一些常见的
ConfigurationHandler
基类,以简化创建自定义配置节、集合和元素的过程

我最后得到的是:

ConfigurationSectionBase
类是泛型的,将
tconfementCollection作为{ConfigurationElementCollection,New}
作为类型约束

ConfigurationSectionBase
类包含一个
Public MustOverride属性集合作为tconfementCollection

其思想是,在使用类库的项目中,他们只需覆盖集合并使用
属性对其进行修饰,例如:

<ConfigurationProperty("CollectionName")>
Public Overrides Property Collection As DerivedConfigurationElementCollection
    Get
        Return TryCast(Me("CollectionName"), DerivedConfigurationElementCollection)
    End Get
    Set(value As DerivedConfigurationElementCollection)
        Me("CollectionName") = value
    End Set
End Property
那么,我的下一个想法是,为什么不将配置处理程序类也抽象出来,并将其移动到基类中呢

这证明更复杂,但我在DLL中的
ConfigurationHandlerBase
类中得到了以下代码:

Protected Function GetCollection(Of TCollection As ConfigurationElementCollection, TSection As {ConfigurationSectionBase(Of TCollection), New})(sectionName as String) As TCollection
    Dim s As TSection = (TryCast(Config.GetSection(sectionName), TSection))
    Return s?.Collection ' AccessViolationException is thrown on this line
为了尝试诊断这个问题,我以与集合相同的方式创建了一个字符串属性(
MustOverride
在DLL中的
ConfigurationSectionBase
类中,在使用应用程序中被重写),然后尝试从类库访问该属性,同样的问题再次出现

因此,我认为问题与
MustOverride
有关,并且DLL代码没有识别出派生类已经重写了属性

如果我从DLL方法返回
t部分
,则访问使用DLL的应用程序中的
集合
属性;我可以很好地访问收藏

奇怪的是,如果我在中放置断点,VisualStudio将非常高兴地向我显示
集合
属性的内容,而不会抛出任何异常

另外,如果我将
(TryCast(Config.GetSection(sectionName),TSection))
替换为
new TSection()
,我仍然会得到一个AccessViolationException,所以就我所见,这与我访问配置文件的事实无关


以前有没有人遇到过这个问题;或者我的下一步是如何排除此异常的?

您是vb.net编译器代码生成错误的受害者,它会损坏ConfigurationHandlerBase.GetCollection()方法的代码。它使用受约束的调用不适当地优化了集合属性的属性getter调用。查看它的最简单方法是在TestCollection.dll程序集上运行PEVerify.exe,尽管错误消息在我看来有误导性:

[IL]:错误:[C:\temp\temp\TestClassLibrary\TestClassLibrary\bin\Debug\TestClassLibrary.dll:TestClassLibrary.ConfigurationHandlerBase`1[TDerivedConfigHandler]::GetCollection[TCollection,TSection][offset 0x00000024]将“this”参数设置为 受约束调用必须具有ByRef类型。 验证testclasslibrary.dll时出现1个错误

但是,搜索错误消息会使您陷入困境。3个月前标记为已修复,我想是它修复的。当这样的修正应用到我们的机器上时,它并不总是显而易见的。今天不行

github问题中提出的解决方案似乎并不有效。我所看到的最简单的解决方法是避免使用elvis运算符,回到基础,重写:

   Dim coll As TCollection = s?.Collection
   Return coll
致:


@HansPassant see看起来像是带有泛型的null条件运算符上的编译器或抖动错误(还没有仔细研究哪一个)。将
Dim coll替换为TCollection=s?.Collection
,将
Dim coll替换为TCollection=IIf(s为Nothing,Nothing,s.Collection)
,问题消失。当然,如果编译器工作正常,这些语句应该是等价的。
   Dim coll As TCollection = s?.Collection
   Return coll
   If s Is Nothing Then return Nothing Else Return s.Collection