为什么我的匿名类型在使用VB.Net但在C#中工作时不能在Clay中工作

时间:2011-05-07 17:57:17

标签: c# vb.net anonymous-types

我正在尝试clay in VB.Net,但发现我无法让一切工作。

这是Clay

这适用于C#

 dynamic c = new ClayFactory();
        var plant = c.Plant(new {LatinName = "test"});
        Console.WriteLine(plant.LatinName);
        Console.ReadLine();

但这在VB.Net中不起作用

Dim c As Object = New ClayFactory
        Dim plant = c.Plant(New With {.LatinName = "test"})
        Console.WriteLine(plant.LatinName)
        Console.ReadLine()

我在VB.Net中收到此错误消息:

> Cannot close over byref parameter
> '$arg1' referenced in lambda ''

如果我能解决这个问题,我不是100%肯定如何解决这个问题。我猜测匿名类型的VB.Net实现略有不同。

我在这一行得到错误:

Dim plant = c.Plant(New With {.LatinName = "test"})

如果有人能向我解释,我将不胜感激。

IL似乎不同了。

对于VB,私有字段Latinname是这样的:

.field private initonly !T0 $LatinName

对于C#,它是:

.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 ) 

公共方法Get_LatinName就是这个。

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

这些是主要方法:

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

C#和VB版本没什么两样的。好像C#版本做得更多。

1 个答案:

答案 0 :(得分:2)

我对Clay一无所知,但C#匿名类型与VB之间存在一个潜在的重要区别:C#匿名类型始终具有只读属性,而默认情况下,VB的是可变的。

在VB中,只有只读属性用于生成相等和哈希码。可以使用Key关键字指定这些内容。所以为了更接近你的C#代码,VB应该是:

Dim c As Object = New ClayFactory
Dim plant = c.Plant(New With { Key .LatinName = "test"})
Console.WriteLine(plant.LatinName)
Console.ReadLine()

尝试一下,看看是否有帮助:)