I recently installed Visual Studio 2019 after using 2017. I have a vb.net web api application that I develop for and every since I started building the project in 2019, I am receiving errors that never occurred before in 2017. I have previously working code that was performing a null check and count greater than 0 check on a dictionary (dictionary1?.Count > 0). This code is failing to check for nothing and my next check is throwing Object Reference must be set to an instance of an object because my dictionary is nothing. It only seems to happen when I build it with 2019 on my computer. None of my team members appear to have this same issue. Does anyone know what I could have missed in the install? Do I need to reinstall 2019 to fix the issue?
Edit
Null Reference Exception Example
I also had some issues with VB.NET solution files in 2019 that I did NOT have with 2017. I never could figure out what was wrong exactly, so I created a "new" project in 2019, and then just copied by code in into the new project. It was a pain, but it worked. So far I've been on 2019 without any further issues.
I've used the following code on VS 2017 and 2019, in an netcore (2019) and netstd472 (both 2017 and 2019) app:
Sub Main(args As String())
Dim d As Dictionary(Of String, String) = Nothing
Dim k As KeyValuePair(Of String, String) = Nothing
If d?.Count > 0 AndAlso d.ContainsKey(k.Key) Then
End If
End Sub
None of them throw an exception.
Here's the generated IL for the netstd, built with 2017's Microsoft (R) Build Engine version 15.9.21+g9802d43bc3 for .NET Framework:
.method public static void Main(string[] args) cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 51 (0x33)
.maxstack 2
.locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<string,string> d,
[1] valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,string> k,
[2] bool V_2)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloca.s k
IL_0005: initobj valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,string>
IL_000b: ldloc.0
IL_000c: brtrue.s IL_0011
IL_000e: ldc.i4.0
IL_000f: br.s IL_001a
IL_0011: ldloc.0
IL_0012: call instance int32 class [mscorlib]System.Collections.Generic.Dictionary`2<string,string>::get_Count()
IL_0017: ldc.i4.0
IL_0018: cgt
IL_001a: brfalse.s IL_002b
IL_001c: ldloc.0
IL_001d: ldloca.s k
IL_001f: call instance !0 valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,string>::get_Key()
IL_0024: callvirt instance bool class [mscorlib]System.Collections.Generic.Dictionary`2<string,string>::ContainsKey(!0)
IL_0029: br.s IL_002c
IL_002b: ldc.i4.0
IL_002c: stloc.2
IL_002d: ldloc.2
IL_002e: brfalse.s IL_0031
IL_0030: nop
IL_0031: nop
IL_0032: ret
} // end of method Module1::Main
and for the netcore31 built with 2019's Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Framework:
.method public static void Main(string[] args) cil managed
{
.entrypoint
.custom instance void [System.Runtime]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 51 (0x33)
.maxstack 2
.locals init (class [System.Collections]System.Collections.Generic.Dictionary`2<string,string> V_0,
valuetype [System.Runtime]System.Collections.Generic.KeyValuePair`2<string,string> V_1,
bool V_2)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloca.s V_1
IL_0005: initobj valuetype [System.Runtime]System.Collections.Generic.KeyValuePair`2<string,string>
IL_000b: ldloc.0
IL_000c: brtrue.s IL_0011
IL_000e: ldc.i4.0
IL_000f: br.s IL_001a
IL_0011: ldloc.0
IL_0012: call instance int32 class [System.Collections]System.Collections.Generic.Dictionary`2<string,string>::get_Count()
IL_0017: ldc.i4.0
IL_0018: cgt
IL_001a: brfalse.s IL_002b
IL_001c: ldloc.0
IL_001d: ldloca.s V_1
IL_001f: call instance !0 valuetype [System.Runtime]System.Collections.Generic.KeyValuePair`2<string,string>::get_Key()
IL_0024: callvirt instance bool class [System.Collections]System.Collections.Generic.Dictionary`2<string,string>::ContainsKey(!0)
IL_0029: br.s IL_002c
IL_002b: ldc.i4.0
IL_002c: stloc.2
IL_002d: ldloc.2
IL_002e: brfalse.s IL_0031
IL_0030: nop
IL_0031: nop
IL_0032: ret
} // end of method Program::Main
Hope it's of some use
Update
Though the above code doesn't crash, this does:
Sub Main(args As String())
Dim d As Dictionary(Of String, String) = Nothing
Dim k As KeyValuePair(Of String, String) = Nothing
Dim x = d?.Count > 0
If x AndAlso d.ContainsKey(k.Key) Then
End If
End Sub
Here's the IL:
.method public static void Main(string[] args) cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 112 (0x70)
.maxstack 2
.locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<string,string> d,
[1] valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,string> k,
[2] valuetype [mscorlib]System.Nullable`1<bool> x,
[3] valuetype [mscorlib]System.Nullable`1<bool> V_3,
[4] bool V_4,
[5] valuetype [mscorlib]System.Nullable`1<bool> V_5)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloca.s k
IL_0005: initobj valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,string>
IL_000b: ldloc.0
IL_000c: brtrue.s IL_0019
IL_000e: ldloca.s V_3
IL_0010: initobj valuetype [mscorlib]System.Nullable`1<bool>
IL_0016: ldloc.3
IL_0017: br.s IL_0027
IL_0019: ldloc.0
IL_001a: call instance int32 class [mscorlib]System.Collections.Generic.Dictionary`2<string,string>::get_Count()
IL_001f: ldc.i4.0
IL_0020: cgt
IL_0022: newobj instance void valuetype [mscorlib]System.Nullable`1<bool>::.ctor(!0)
IL_0027: stloc.2
IL_0028: ldloc.2
IL_0029: dup
IL_002a: stloc.3
IL_002b: stloc.s V_5
IL_002d: ldloca.s V_5
IL_002f: call instance bool valuetype [mscorlib]System.Nullable`1<bool>::get_HasValue()
IL_0034: brfalse.s IL_003f
IL_0036: ldloca.s V_3
IL_0038: call instance !0 valuetype [mscorlib]System.Nullable`1<bool>::GetValueOrDefault()
IL_003d: brfalse.s IL_0059
IL_003f: ldloc.0
IL_0040: ldloca.s k
IL_0042: call instance !0 valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,string>::get_Key()
IL_0047: callvirt instance bool class [mscorlib]System.Collections.Generic.Dictionary`2<string,string>::ContainsKey(!0)
IL_004c: brtrue.s IL_0056
IL_004e: ldc.i4.0
IL_004f: newobj instance void valuetype [mscorlib]System.Nullable`1<bool>::.ctor(!0)
IL_0054: br.s IL_0057
IL_0056: ldloc.3
IL_0057: br.s IL_005f
IL_0059: ldc.i4.0
IL_005a: newobj instance void valuetype [mscorlib]System.Nullable`1<bool>::.ctor(!0)
IL_005f: stloc.3
IL_0060: ldloca.s V_3
IL_0062: call instance !0 valuetype [mscorlib]System.Nullable`1<bool>::GetValueOrDefault()
IL_0067: stloc.s V_4
IL_0069: ldloc.s V_4
IL_006b: brfalse.s IL_006e
IL_006d: nop
IL_006e: nop
IL_006f: ret
} // end of method Module1::Main
I don't really have an explanation though
I am trying to understand why this is invalid IL code and/or what would cause this fault.
The exception thrown is:
System.InvalidProgramException: Invalid IL code in
away3d.containers.View3D:updateBackBuffer (): IL_0023: brfalse
IL_00ba
I disassembled using monodis and the method that is being called (updateBackBuffer) and throwing the error follows below, but I can not spot anything wrong with the branch if false statement or the IL around it:
// method line 841
.method family virtual hidebysig newslot
instance default void updateBackBuffer () cil managed
{
// Method begins at RVA 0x1e4d4
// Code size 226 (0xe2)
.maxstack 5
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld class away3d.core.managers.Stage3DProxy away3d.containers.View3D::_stage3DProxy
IL_0007: callvirt instance class [pscorlib_monomac]flash.display3D.Context3D class away3d.core.managers.Stage3DProxy::get_context3D()
IL_000c: brfalse IL_00e1
IL_0011: ldarg.0
IL_0012: ldfld bool away3d.containers.View3D::_shareContext
IL_0017: brtrue IL_00e1
IL_001c: nop
IL_001d: ldarg.0
IL_001e: ldfld float64 away3d.containers.View3D::_width
IL_0023: brfalse IL_00ba
IL_0028: ldarg.0
IL_0029: ldfld float64 away3d.containers.View3D::_height
IL_002e: brfalse IL_00ba
IL_0033: nop
IL_0034: ldarg.0
IL_0035: ldfld class away3d.core.managers.Stage3DProxy away3d.containers.View3D::_stage3DProxy
IL_003a: callvirt instance bool class away3d.core.managers.Stage3DProxy::get_usesSoftwareRendering()
IL_003f: brfalse IL_008c
IL_0044: nop
IL_0045: ldarg.0
IL_0046: ldfld float64 away3d.containers.View3D::_width
IL_004b: ldc.r8 2048.
IL_0054: ble.un IL_0068
IL_0059: ldarg.0
IL_005a: ldc.r8 2048.
IL_0063: stfld float64 away3d.containers.View3D::_width
IL_0068: ldarg.0
IL_0069: ldfld float64 away3d.containers.View3D::_height
IL_006e: ldc.r8 2048.
IL_0077: ble.un IL_008b
IL_007c: ldarg.0
IL_007d: ldc.r8 2048.
IL_0086: stfld float64 away3d.containers.View3D::_height
IL_008b: nop
IL_008c: ldarg.0
IL_008d: ldfld class away3d.core.managers.Stage3DProxy away3d.containers.View3D::_stage3DProxy
IL_0092: ldarg.0
IL_0093: ldfld float64 away3d.containers.View3D::_width
IL_0098: conv.i4
IL_0099: ldarg.0
IL_009a: ldfld float64 away3d.containers.View3D::_height
IL_009f: conv.i4
IL_00a0: ldarg.0
IL_00a1: ldfld unsigned int32 away3d.containers.View3D::_antiAlias
IL_00a6: conv.i4
IL_00a7: ldc.i4.1
IL_00a8: callvirt instance void class away3d.core.managers.Stage3DProxy::configureBackBuffer(int32, int32, int32, bool)
IL_00ad: ldarg.0
IL_00ae: ldc.i4.0
IL_00af: stfld bool away3d.containers.View3D::_backBufferInvalid
IL_00b4: nop
IL_00b5: br IL_00e0
IL_00ba: nop
IL_00bb: ldarg.0
IL_00bc: ldarg.0
IL_00bd: callvirt instance class [pscorlib_monomac]flash.display.Stage class [pscorlib_monomac]flash.display.DisplayObject::get_stage()
IL_00c2: callvirt instance int32 class [pscorlib_monomac]flash.display.Stage::get_stageWidth()
IL_00c7: conv.r8
IL_00c8: callvirt instance void class [pscorlib_monomac]flash.display.DisplayObject::set_width(float64)
IL_00cd: ldarg.0
IL_00ce: ldarg.0
IL_00cf: callvirt instance class [pscorlib_monomac]flash.display.Stage class [pscorlib_monomac]flash.display.DisplayObject::get_stage()
IL_00d4: callvirt instance int32 class [pscorlib_monomac]flash.display.Stage::get_stageHeight()
IL_00d9: conv.r8
IL_00da: callvirt instance void class [pscorlib_monomac]flash.display.DisplayObject::set_height(float64)
IL_00df: nop
IL_00e0: nop
IL_00e1: ret
} // end of method View3D::updateBackBuffer
Maybe it's because loaded value at that place is not boolean?
This code behaves differently in VB12 vs VB14.
How can we force the vb compiler to keep the old behavior? The new behavior throws an unhandled excetion because of the new call to Microsoft.VisualBasic.CompilerServices.Conversions::ToDate(string) in the VB14 IL version.
Exception
Unhandled Exception: System.InvalidCastException: Conversion from string "" to type 'Date' is not valid.
at Microsoft.VisualBasic.CompilerServices.Conversions.ToDate(String Value)
at VBConsoleApplication1.Module1.Main() in c:\Module1.vb:line 7
Source Code
Module Module1
Sub Main()
Dim dt As New DateTime
dt = vbNullString
Console.WriteLine(dt)
Console.WriteLine("Any Key")
Console.ReadKey(False)
End Sub
End Module
VB12 IL
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 49 (0x31)
.maxstack 1
.locals init ([0] valuetype [mscorlib]System.DateTime dt,
[1] valuetype [mscorlib]System.DateTime VB$t_date$N0)
IL_0000: nop
IL_0001: ldloca.s dt
IL_0003: initobj [mscorlib]System.DateTime
IL_0009: ldloca.s dt
IL_000b: initobj [mscorlib]System.DateTime
IL_0011: ldloc.0
IL_0012: box [mscorlib]System.DateTime
IL_0017: call void [mscorlib]System.Console::WriteLine(object)
IL_001c: nop
IL_001d: ldstr "Any Key"
IL_0022: call void [mscorlib]System.Console::WriteLine(string)
IL_0027: nop
IL_0028: ldc.i4.0
IL_0029: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey(bool)
IL_002e: pop
IL_002f: nop
IL_0030: ret
} // end of method Module1::Main
VB14 IL
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 47 (0x2f)
.maxstack 1
.locals init ([0] valuetype [mscorlib]System.DateTime dt)
IL_0000: nop
IL_0001: ldloca.s dt
IL_0003: initobj [mscorlib]System.DateTime
IL_0009: ldnull
IL_000a: call valuetype [mscorlib]System.DateTime [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToDate(string)
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: box [mscorlib]System.DateTime
IL_0016: call void [mscorlib]System.Console::WriteLine(object)
IL_001b: nop
IL_001c: ldstr "Any Key"
IL_0021: call void [mscorlib]System.Console::WriteLine(string)
IL_0026: nop
IL_0027: ldc.i4.0
IL_0028: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey(bool)
IL_002d: pop
IL_002e: ret
} // end of method Module1::Main
I'm using the following code to extend my Service-Context with a FullName on clientside:
public partial class Customer {
public string FullName
{
get
{
return string.Concat(LastName, (FirstName == "" ? "" : ", "), FirstName);
}
}
}
That works fine, until it comes to the point where I need to Add a new Object to the Context with the AddOBject Method. It throws an Exception. When I remove the FullName extension th AddObject method saves the new Object to the database.
What is the best way to extend my Context and still make it Update- and Insertable?
Edit: The DataServiceRequest Exception:
System.Data.Services.Client.DataServiceRequestException was not handled by user code.
HResult=-2146233079
Message=Fehler beim Verarbeiten dieser Anforderung.
Source=Microsoft.Data.Services.Client.WindowsStore
StackTrace:
at System.Data.Services.Client.SaveResult.HandleResponse()
at System.Data.Services.Client.BaseSaveResult.EndRequest()
at System.Data.Services.Client.DataServiceContext.EndSaveChanges(IAsyncResult asyncResult)
at Pointsale.Client.Service.PointsaleEntities.<SaveChanges>b__0(IAsyncResult asResult) in c:\Users\Jan\Desktop\pointsale_worksapce\pointsale.client\Helper\TenantHelper.cs:line 98
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
InnerException: System.Data.Services.Client.DataServiceClientException
HResult=-2146233079
Message=<?xml version="1.0" encoding="utf-8"?><m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><m:code /><m:message xml:lang="de-DE">Error occurred while processing this request.</m:message></m:error>
StatusCode=400
InnerException:
And the SaveChanges method overide to get it async:
public async Task<DataServiceResponse> SaveChanges()
{
var queryTask = Task.Factory.FromAsync(this.BeginSaveChanges(null, null), asResult =>
{
var result = this.EndSaveChanges(asResult);
return result;
});
return await queryTask;
}
On EndSaveChanges the error occures.
I'm an absolute beginner, you see. Say I have a string object on the stack and want to get the number of characters in it - its .Length property. How would I get the int32 number hidden inside?
Many thanks in advance!
There's really no such thing as properties in IL. There are only fields and methods. The C# property construct is translated to get_PropertyName and set_PropertyName methods by the compiler, so you have to call these methods to access the property.
Sample (debug) IL for code
var s = "hello world";
var i = s.Length;
IL
.locals init ([0] string s,
[1] int32 i)
IL_0000: nop
IL_0001: ldstr "hello world"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_000d: stloc.1
As you can see the Length property is accessed via the call to get_Length.
I cheated ... I took the following C# code and took a look at it in ildasm/Reflector
static void Main(string[] args)
{
string h = "hello world";
int i = h.Length;
}
is equivalent to
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] string h,
[1] int32 i)
L_0000: nop
L_0001: ldstr "hello world"
L_0006: stloc.0
L_0007: ldloc.0
L_0008: callvirt instance int32 [mscorlib]System.String::get_Length()
L_000d: stloc.1
L_000e: ret
}