Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何初始化惰性列表?_.net_Vb.net_Lazy Evaluation_Lazy Initialization_Dnlib - Fatal编程技术网

.net 如何初始化惰性列表?

.net 如何初始化惰性列表?,.net,vb.net,lazy-evaluation,lazy-initialization,dnlib,.net,Vb.net,Lazy Evaluation,Lazy Initialization,Dnlib,我读过,但实际上我不知道如何初始化里面的对象 此函数返回一个LazyList,它是一种类型的自定义实现 当我尝试读取LazyList的任何项的属性时,我得到一个NullReferenceException异常,我想这是因为对象未初始化?”原因请注意,lazylist项计数为“2”,我完全确定我尝试读取的属性不能为null Imports dnlib.DotNet Imports dnlib.DotNet.Emit Imports dnlib.Utils Dim methods As L

我读过,但实际上我不知道如何初始化里面的对象

此函数返回一个
LazyList
,它是一种类型的自定义实现

当我尝试读取LazyList的任何项的属性时,我得到一个
NullReferenceException
异常,我想这是因为对象未初始化?”原因请注意,lazylist项计数为“2”,我完全确定我尝试读取的属性不能为null

Imports dnlib.DotNet
Imports dnlib.DotNet.Emit
Imports dnlib.Utils

    Dim methods As LazyList(Of MethodDef) = GetMethods("C:\WindowsApplication.exe", "Main")

    MsgBox(methods.IsInitialized(0)) ' Result: False
    MsgBox(methods.Count) ' Result: 2

    For Each method As MethodDef In methods

        ' NullReferenceException exception here:
        MsgBox(method.Name)

        ' NullReferenceException exception here too (reading m.hasbody):
        If method.HasBody Then
            Dim sb As New System.Text.StringBuilder
            With sb
                .AppendLine(String.Format("Method Instructions: {0}", Environment.NewLine &
                                          String.Join(Environment.NewLine, method.Body.Instructions)))
            End With
            Debug.WriteLine(sb.ToString)
        End If

    Next method
如果我试图重现我在上面代码中所做的(尝试读取属性),但是在函数内部,那么一切都会按照预期进行,没有任何nullreference异常。。。如本例所示:

public function GetMethods (...)

' deleted code...

        If t.HasMethods AndAlso t.Name.String.Equals(TypeName, StringComparison.OrdinalIgnoreCase) Then

           methods = t.Methods
            For Each m In methods
                MsgBox(m.Name) ' no exceptions
                MsgBox(m.HasBody) ' no exceptions
            Next

       End If

' deleted code...

end function
PS:导入来自库

更新:

我想用更多更好的例子来解释这个问题

在继续解释之前有两件事:

我确保在所有示例中,
TypeName
参数存在,并且找到了iis,我确保函数返回的对象集合从不为空,它有一个集合。计数2,正如我在问题开始时解释的,所以这就是问题所在


好的,下一个函数返回一个对象列表,这些对象带有一个名为
HasBody
的属性,但是这个属性总是为空(抛出NullReference异常),当它不应该为空时,集合中包含的两个项的值都应该为True

Public Function GetMethods(ByVal Assembly As String,
                           ByVal TypeName As String) As List(Of MethodDef)

    Dim methods As List(Of MethodDef) = Nothing

    Using ass As ModuleDefMD = ModuleDefMD.Load(Assembly)

        For Each t As TypeDef In ass.GetTypes

            If t.HasMethods AndAlso t.Name.String.Equals(TypeName, StringComparison.OrdinalIgnoreCase) Then

                methods = t.Methods.ToList
                Exit For

            End If

        Next t

        Return methods

    End Using

End Function
另一方面,如果我在函数中执行了荒谬的修改(请参见与
tmp
对象相关的更改),函数将返回一个对象列表,其中
HasBody
属性被初始化,并且不是空的,返回的列表中包含的两项是一个值为True的
HasBody
属性

Public Function GetMethods(ByVal Assembly As String,
                           ByVal TypeName As String) As List(Of MethodDef)

    Dim methods As List(Of MethodDef) = Nothing

    Dim tmp As Object

    Using ass As ModuleDefMD = ModuleDefMD.Load(Assembly)

        For Each t As TypeDef In ass.GetTypes

            If t.HasMethods AndAlso t.Name.String.Equals(TypeName, StringComparison.OrdinalIgnoreCase) Then

                methods = t.Methods.ToList
                For Each m In methods
                    tmp = m.HasBody
                Next

                Exit For

            End If

        Next t

        Return methods

    End Using

End Function
那么这里的问题在哪里以及如何解决呢?也许这是这种情况的暂时解决方案,但是返回函数的
methoddef
对象包含很多属性,我需要在将来访问比
HasBody
更多的属性,所以我真的不能“赋值”函数中
tmp
对象的每个属性以一种丑陋的方式解决该问题

在这两种情况下,用于循环返回列表的代码是:

注意:请记住,对于第一个函数,我不能解析
方法.hasbody
属性,也不能解析
方法.body.instructions
属性,两者都会引发NullReference异常

但是通过修改后的函数,我可以解析
方法.hasbody
属性,前提是我在返回列表之前已将其分配给函数中的
tmp
变量,如果
方法.body.instructions
属性也是如此

    Dim methods As List(Of MethodDef) =
        GetMethods("C:\WindowsApplication.exe", "Main")

    For Each method As MethodDef In methods

        MsgBox(method.Name)

        If method.HasBody Then
            Dim sb As New System.Text.StringBuilder
            With sb
                .AppendLine(String.Format("Method Instructions: {0}", Environment.NewLine &
                                          String.Join(Environment.NewLine, method.Body.Instructions)))
            End With
            MsgBox(sb.ToString)
        End If

    Next method

我认为这是第一个问题:

Public Function GetMethods(ByVal Assembly As String,
                       ByVal TypeName As String) 'As List(Of MethodDef) 
指定返回类型,它可能会工作:
As LazyList(属于MethodDef)

当在程序集中找不到
TypeName
时,也会发生这种情况。在这种情况下,您的懒散列表仍然是空的,并导致NRE。你应该查看报税表-我认为这与懒汉名单无关(目前):

试验台:

Dim methods As LazyList(Of MethodDef) = Nothing
在按钮中单击:

methods = Test_Handler("Test2")

For Each meth As MethodDef In methods
    If meth.HasBody Then
        Console.WriteLine("{0} has a body", meth.Name)
    Else
        Console.WriteLine("{0} has NO body", meth.Name)
    End If
Next
测试处理程序本质上就是您所拥有的&=
(MethodDef的)懒散列表
。输出:

.ctor has a body
testfunction has a body
Foo has a body
Bar has a body
ziggy has a body
接下来可能会出现更大的问题:。。。我不明白如何初始化里面的对象

LazyList中存储的是这些
MethodDef
对象——它们已经实例化了
TypeDef.Methods
实际上返回的是
MethodDef
的IList,其中包含懒散列表的唯一原因是您的代码以这种方式存储它们

如果你想调用他们描述的方法,我很确定你不能用
MethodDef
作为起点。它们只是描述方法特征的元数据。您已经知道它们来自
TypeName
,因此要调用其中一个方法,您必须拥有该类型的实例

不知道您想做什么,但是对于元数据集合来说,似乎不需要懒散列表


对象浏览器中
方法
的定义是
IList
,源代码还显示:

public ThreadSafe.IList<MethodDef> Methods
您可能太聪明了,尝试只执行以下操作:
返回t.Methods
,并获得有关LastList转换到List的转换错误。但是,您得到的方法对象集已经实例化,因此如果您得到的是NREs,则可能会有其他问题


这解决了问题:

Using ass As ModuleDefMD = ModuleDefMD.Load(Assembly)
方法def的列表在内部是一个LazyList,在调用其上的属性或方法之前不会实例化。举例来说,他们(显然)需要访问创建他们的东西。因此,请参考一些无害的内容,以便处理
ModuleDefMD

Dim methods As New List(Of MethodDef)
Dim b As Boolean

Using modDef As ModuleDefMD = ModuleDefMD.Load("C:\Temp\ConsoleApplication1.exe")
    For Each t As TypeDef In modDef.GetTypes

        ' stupid way to drill, but will work for demo purposes
        If t.Name.Equals(typeName) Then

            For Each m As MethodDef In t.Methods
                b = m.HasBody

                methods.Add(m)

            Next
            Exit For
        End If

    Next
End Using
Return methods

这或多或少就是Tmp对象所做的。你称之为丑陋,但由于源代码是一个懒人列表,它要么是丑陋的,要么就是通过
modDef
引用解决问题。

当你得到异常时,什么对象是空的?@usr“HasBody”和“Body.Instructions”属性,但我确实使用了很多我没有验证是否为空的属性(不应为空)。如果可以,请查看我的问题更新,谢谢您的评论。将返回类型设置为“LazyList(Of MethodDef)”'没有解决问题。您还说,之所以涉及懒人,唯一的原因是因为我,但不是,我真的不想使用懒人,但如果我在函数中得到tu返回的数据类型,它就是一个懒人列表,如上面的代码所示(t.Methods.GetType.Name)。所有评论均未解决问题,请查看我的问题更新,我在其中发布了有助于更好理解问题的代码,感谢您的回答两次编辑…您不能
Private Function Test_Handler(typeName As String) As List(Of MethodDef)

    Dim modDef As ModuleDefMD = ModuleDefMD.Load("C:\Temp\ConsoleApplication1.exe")
    Dim methods As New List(Of MethodDef)

    For Each t As TypeDef In modDef.GetTypes

        ' stupid way to drill, but will work for demo purposes
        If t.Name.Equals(typeName) Then

            'methods = t.Methods
            methods.AddRange(t.Methods.ToArray)

            Exit For
        End If

    Next

    Return methods

End Function
Using ass As ModuleDefMD = ModuleDefMD.Load(Assembly)
Dim methods As New List(Of MethodDef)
Dim b As Boolean

Using modDef As ModuleDefMD = ModuleDefMD.Load("C:\Temp\ConsoleApplication1.exe")
    For Each t As TypeDef In modDef.GetTypes

        ' stupid way to drill, but will work for demo purposes
        If t.Name.Equals(typeName) Then

            For Each m As MethodDef In t.Methods
                b = m.HasBody

                methods.Add(m)

            Next
            Exit For
        End If

    Next
End Using
Return methods