Open denis-troller opened 4 years ago
Any news on this ? I still have the same behavior on VIsual Studio 16.8 and it is a BIG problem. Code that used to work in .net framework does not work when compiled against netstandard...
I managed to reproduce it with a simpler method: 1 - Create a new solution 2 - Create a new Visual Basic Library project (netstandard 2.0) named Lib 3 - Create two classes:
Public Class TestValue
Implements IConvertible
Public Function GetTypeCode() As TypeCode Implements IConvertible.GetTypeCode
Return TypeCode.Double
End Function
Public Function ToBoolean(provider As IFormatProvider) As Boolean Implements IConvertible.ToBoolean
Throw New NotImplementedException()
End Function
Public Function ToChar(provider As IFormatProvider) As Char Implements IConvertible.ToChar
Throw New NotImplementedException()
End Function
Public Function ToSByte(provider As IFormatProvider) As SByte Implements IConvertible.ToSByte
Throw New NotImplementedException()
End Function
Public Function ToByte(provider As IFormatProvider) As Byte Implements IConvertible.ToByte
Throw New NotImplementedException()
End Function
Public Function ToInt16(provider As IFormatProvider) As Short Implements IConvertible.ToInt16
Throw New NotImplementedException()
End Function
Public Function ToUInt16(provider As IFormatProvider) As UShort Implements IConvertible.ToUInt16
Throw New NotImplementedException()
End Function
Public Function ToInt32(provider As IFormatProvider) As Integer Implements IConvertible.ToInt32
Throw New NotImplementedException()
End Function
Public Function ToUInt32(provider As IFormatProvider) As UInteger Implements IConvertible.ToUInt32
Throw New NotImplementedException()
End Function
Public Function ToInt64(provider As IFormatProvider) As Long Implements IConvertible.ToInt64
Throw New NotImplementedException()
End Function
Public Function ToUInt64(provider As IFormatProvider) As ULong Implements IConvertible.ToUInt64
Throw New NotImplementedException()
End Function
Public Function ToSingle(provider As IFormatProvider) As Single Implements IConvertible.ToSingle
Throw New NotImplementedException()
End Function
Public Function ToDouble(provider As IFormatProvider) As Double Implements IConvertible.ToDouble
Return 42.0
End Function
Public Function ToDecimal(provider As IFormatProvider) As Decimal Implements IConvertible.ToDecimal
Throw New NotImplementedException()
End Function
Public Function ToDateTime(provider As IFormatProvider) As Date Implements IConvertible.ToDateTime
Throw New NotImplementedException()
End Function
Public Function IConvertible_ToString(provider As IFormatProvider) As String Implements IConvertible.ToString
Throw New NotImplementedException()
End Function
Public Function ToType(conversionType As Type, provider As IFormatProvider) As Object Implements IConvertible.ToType
Throw New NotImplementedException()
End Function
End Class
Public Class Tester
Public Function GetValue() as Object
return 42.0
End Function
Public Function GetValue2() as Object
return New TestValue()
End Function
Public Function Test1() as Double
return Cdbl(GetValue())
End Function
Public Function Test2() as Double
return Cdbl(GetValue2())
End Function
End Class
4 - Create a .net Framework 4.8 console project and add a reference to the library In Main:
Sub Main(args As String())
Dim t As New Lib.Test()
Dim v = t.Test1()
Console.Out.WriteLine(v)
Dim v2 = t.Test2()
Console.Out.WriteLine(v2)
End Sub
5 - Create a .net 5.0 console project and add a reference to the library In Main (same as above):
Sub Main(args As String())
Dim t As New Lib.Test()
Dim v = t.Test1()
Console.Out.WriteLine(v)
Dim v2 = t.Test2()
Console.Out.WriteLine(v2)
End Sub
If you execute the net50 project, it throws an InvalidCastException
on the call to t.Test2()
Decompiling Lib.dll shows that the version generated for the .net50 exe contains the suspect code in my original submission(without support for IConvertible).
If you execute the 4.8 project, it generates the same error.
If you double-target LIB to net4.8 and netstandard2.0, then the problem stays for the net5.0 project, but disappears for net4.8 The version generated for 4.8 does not have the suspect code and links to the normal Visual Basic implementation. Finally if you double-target LIB to net4.8 and net50, then everything works fine. However, this is not desirable in our setup because the build process would have to be reworked severly if EVERY library in our system where to be double-targeted instead of using netstandard (which works fine apart from that).
Any idea for a resolution or a workaround ?
I have exactly the same issue. Do you guys have a fix or a workaround?
Version Used: Visual Studio 2019 v16.7.2 (Net Framework 7.4.2 / NetStandard 2.0 / NetCore 3.1)
Steps to Reproduce:
Expected Behavior:
The value should be converted acording to our implementation of IConvertible.ToDouble()
Actual Behavior:
An InvalidCastException is raised.
Looking further using DnSpy, it appears the code for Microsoft.VisualBasic.CompilerServices has found itself embedded in our dll. However, it is NOT the code that is normally in the corresponding class in the separate library. It makes no provisions for checking IConvertible and fails becuase not correct conversion is found.
Here is the code that has been embedded:
We have no idea what triggered the embedding of this in our project. Creating a new minimal project from scratch with VS2019 works and the problem does not appear. I tracked this exact same code to the Microsoft.VisaulBasic nuget package. I also found it in the repository here under src/Compilers/VisualBasic/Portable/Symbols/EmbeddedSymbols/VbCoreSourceText.vb, but I do not understand what triggers its inclusion in our dll when a brand new (simple) project does not have it.
I am logging this here because I imagine this is a compiler-related feature that embedded this strange code. Would really appreciate some help...