I was trying out clay in VB.Net but found that I could not get everything to work.
Here is Clay
This works in C#
dynamic c = new ClayFactory();
var plant = c.Plant(new {LatinName = "test"});
Console.WriteLine(plant.LatinName);
Console.ReadLine();
but this does not work in VB.Net
Dim c As Object = New ClayFactory
Dim plant = c.Plant(New With {.LatinName = "test"})
Console.WriteLine(plant.LatinName)
Console.ReadLine()
I get this error message in VB.Net:
> Cannot close over byref parameter
> '$arg1' referenced in lambda ''
I'm not 100% sure how to solve this if I can even solve it. I'm guessing the VB.Net implementation of anonymous types is slightly different.
I get the error on this line:
Dim plant = c.Plant(New With {.LatinName = "test"})
I would appreciate if someone could explain this to me.
The IL seems to be quit different.
For VB the private field Latinname is this:
.field private initonly !T0 $LatinName
For C# it is:
.field private initonly !'<LatinName>j__TPar' '<LatinName>i__Field'
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
And the public method Get_LatinName is this.
VB:
.method public specialname instance !T0 get_LatinName() cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) // Code size 11 (0xb) .maxstack 1 .locals init (!T0 V_0) IL_0000: ldarg.0 IL_0001: ldfld !0 class VB$AnonymousType_0`1::$LatinName IL_0006: stloc.0 IL_0007: br.s IL_0009 IL_0009: ldloc.0 IL_000a: ret } // end of method VB$AnonymousType_0`1::get_LatinName
C#:
.method public hidebysig specialname instance !'j__TPar' get_LatinName() cil managed { // Code size 11 (0xb) .maxstack 1 .locals init (!'j__TPar' V_0) IL_0000: ldarg.0 IL_0001: ldfld !0 class 'f__AnonymousType0`1'j__TPar'>::'i__Field' IL_0006: stloc.0 IL_0007: br.s IL_0009 IL_0009: ldloc.0 IL_000a: ret } // end of method 'f__AnonymousType0`1'::get_LatinName
And these are the main methods:
VB:
.method public static void Main() cil managed { .entrypoint .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) // Code size 90 (0x5a) .maxstack 7 .locals init ([0] object c, [1] object plant, [2] class VB$AnonymousType_0`1 VB$t_ref$S0, [3] object[] VB$t_array$S0) IL_0000: nop IL_0001: newobj instance void [ClaySharp]ClaySharp.ClayFactory::.ctor() IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: ldnull IL_0009: ldstr "Plant" IL_000e: ldc.i4.1 IL_000f: newarr [mscorlib]System.Object IL_0014: stloc.3 IL_0015: ldloc.3 IL_0016: ldc.i4.0 IL_0017: ldstr "test" IL_001c: newobj instance void class VB$AnonymousType_0`1::.ctor(!0) IL_0021: stelem.ref IL_0022: nop IL_0023: ldloc.3 IL_0024: ldnull IL_0025: ldnull IL_0026: ldnull IL_0027: call object [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.NewLateBinding::LateGet(object, class [mscorlib]System.Type, string, object[], string[], class [mscorlib]System.Type[], bool[]) IL_002c: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object) IL_0031: stloc.1 IL_0032: ldloc.1 IL_0033: ldnull IL_0034: ldstr "LatinName" IL_0039: ldc.i4.0 IL_003a: newarr [mscorlib]System.Object IL_003f: ldnull IL_0040: ldnull IL_0041: ldnull IL_0042: call object [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.NewLateBinding::LateGet(object, class [mscorlib]System.Type, string, object[], string[], class [mscorlib]System.Type[], bool[]) IL_0047: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object) IL_004c: call void [mscorlib]System.Console::WriteLine(object) IL_0051: nop IL_0052: call string [mscorlib]System.Console::ReadLine() IL_0057: pop IL_0058: nop IL_0059: ret } // end of method Module1::Main
C#:
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // Code size 299 (0x12b) .maxstack 10 .locals init ([0] object c, [1] object plant, [2] class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo[] CS$0$0000) IL_0000: nop IL_0001: newobj instance void [ClaySharp]ClaySharp.ClayFactory::.ctor() IL_0006: stloc.0 IL_0007: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1f__AnonymousType0`1',object>> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site1' IL_000c: brtrue.s IL_004c IL_000e: ldc.i4.0 IL_000f: ldstr "Plant" IL_0014: ldnull IL_0015: ldtoken ConsoleApplication2.Program IL_001a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) IL_001f: ldc.i4.2 IL_0020: newarr [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo IL_0025: stloc.2 IL_0026: ldloc.2 IL_0027: ldc.i4.0 IL_0028: ldc.i4.0 IL_0029: ldnull IL_002a: call class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string) IL_002f: stelem.ref IL_0030: ldloc.2 IL_0031: ldc.i4.1 IL_0032: ldc.i4.1 IL_0033: ldnull IL_0034: call class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string) IL_0039: stelem.ref IL_003a: ldloc.2 IL_003b: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::InvokeMember(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, string, class [mscorlib]System.Collections.Generic.IEnumerable`1, class [mscorlib]System.Type, class [mscorlib]System.Collections.Generic.IEnumerable`1) IL_0040: call class [System.Core]System.Runtime.CompilerServices.CallSite`1 class [System.Core]System.Runtime.CompilerServices.CallSite`1f__AnonymousType0`1',object>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder) IL_0045: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1f__AnonymousType0`1',object>> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site1' IL_004a: br.s IL_004c IL_004c: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1f__AnonymousType0`1',object>> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site1' IL_0051: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1f__AnonymousType0`1',object>>::Target IL_0056: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1f__AnonymousType0`1',object>> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site1' IL_005b: ldloc.0 IL_005c: ldstr "test" IL_0061: newobj instance void class 'f__AnonymousType0`1'::.ctor(!0) IL_0066: callvirt instance !3 class [mscorlib]System.Func`4f__AnonymousType0`1',object>::Invoke(!0, !1, !2) IL_006b: stloc.1 IL_006c: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site2' IL_0071: brtrue.s IL_00b6 IL_0073: ldc.i4 0x100 IL_0078: ldstr "WriteLine" IL_007d: ldnull IL_007e: ldtoken ConsoleApplication2.Program IL_0083: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) IL_0088: ldc.i4.2 IL_0089: newarr [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo IL_008e: stloc.2 IL_008f: ldloc.2 IL_0090: ldc.i4.0 IL_0091: ldc.i4.s 33 IL_0093: ldnull IL_0094: call class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string) IL_0099: stelem.ref IL_009a: ldloc.2 IL_009b: ldc.i4.1 IL_009c: ldc.i4.0 IL_009d: ldnull IL_009e: call class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string) IL_00a3: stelem.ref IL_00a4: ldloc.2 IL_00a5: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::InvokeMember(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, string, class [mscorlib]System.Collections.Generic.IEnumerable`1, class [mscorlib]System.Type, class [mscorlib]System.Collections.Generic.IEnumerable`1) IL_00aa: call class [System.Core]System.Runtime.CompilerServices.CallSite`1 class [System.Core]System.Runtime.CompilerServices.CallSite`1>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder) IL_00af: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site2' IL_00b4: br.s IL_00b6 IL_00b6: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site2' IL_00bb: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1>::Target IL_00c0: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site2' IL_00c5: ldtoken [mscorlib]System.Console IL_00ca: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) IL_00cf: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site3' IL_00d4: brtrue.s IL_0109 IL_00d6: ldc.i4.0 IL_00d7: ldstr "LatinName" IL_00dc: ldtoken ConsoleApplication2.Program IL_00e1: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) IL_00e6: ldc.i4.1 IL_00e7: newarr [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo IL_00ec: stloc.2 IL_00ed: ldloc.2 IL_00ee: ldc.i4.0 IL_00ef: ldc.i4.0 IL_00f0: ldnull IL_00f1: call class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string) IL_00f6: stelem.ref IL_00f7: ldloc.2 IL_00f8: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::GetMember(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, string, class [mscorlib]System.Type, class [mscorlib]System.Collections.Generic.IEnumerable`1) IL_00fd: call class [System.Core]System.Runtime.CompilerServices.CallSite`1 class [System.Core]System.Runtime.CompilerServices.CallSite`1>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder) IL_0102: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site3' IL_0107: br.s IL_0109 IL_0109: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site3' IL_010e: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1>::Target IL_0113: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1> ConsoleApplication2.Program/'o__SiteContainer0'::'p__Site3' IL_0118: ldloc.1 IL_0119: callvirt instance !2 class [mscorlib]System.Func`3::Invoke(!0, !1) IL_011e: callvirt instance void class [mscorlib]System.Action`3::Invoke(!0, !1, !2) IL_0123: nop IL_0124: call string [mscorlib]System.Console::ReadLine() IL_0129: pop IL_012a: ret } // end of method Program::Main
The C# and VB version are nothing alike. Seems like the C# version does a lot more.
In C#, you are allowed to create an anonymous type object with a new keyword without its class definition and var is used to hold the reference of the anonymous types. As shown in the below example, anony_object is an anonymous type object which contains three properties that are s_id, s_name, language.
Essentially an anonymous type is a reference type and can be defined using the var keyword. You can have one or more properties in an anonymous type but all of them are read-only.
Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first. The type name is generated by the compiler and is not available at the source code level. The type of each property is inferred by the compiler.
You create an anonymous type using the new operator with an object initializer syntax. The implicitly typed variable- var is used to hold the reference of anonymous types.
I don't know anything about Clay, but there is one potentially important difference between C# anonymous types and VB ones: C# anonymous types always have read-only properties, whereas by default, VB ones are mutable.
Only the read-only properties are used in equality and hash code generation in VB. These can be specified with the Key
keyword. So to be closer to your C# code, the VB should be:
Dim c As Object = New ClayFactory
Dim plant = c.Plant(New With { Key .LatinName = "test"})
Console.WriteLine(plant.LatinName)
Console.ReadLine()
Give that a try and see whether it helps :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With