【问题标题】:Using for each to iterate class properties使用 for each 来迭代类属性
【发布时间】:2017-03-30 01:19:26
【问题描述】:

我有这门课

Public Class TExperience
    Public ID As Integer
    Public CompanyName As String
    Public Country As String
    Public Years As Integer
    Public Months As Integer
    Public JobTitle As String
    Public Function Arr() As String()
        Return {"ID", "CompanyName", "Country", "Years", "Months", "JobTitle"}
    End Function
End Class

这就是它的工作原理

Public Function Set()
    Dim D As New TExperience
    D.CompanyName = "Any Data"
    D.Country = "Any Data"
    D.ID = "Any Data"
    D.JobTitle = "Any Data"
    D.Months = "Any Data"
End Function

我需要在课堂上用“For Each.....”来交换这个

        D.CompanyName = "Any Data"
        D.Country = "Any Data"
        D.ID = "Any Data"
        D.JobTitle = "Any Data"
        D.Months = "Any Data"

如何做到这一点?

【问题讨论】:

  • For Each 用于迭代集合 - 这里不需要。
  • 有什么办法可以在这里做,或者有什么其他方法可以做我需要的吗?
  • 我完全不清楚您要做什么。要通过一种方法“设置”所有这些成员,我会使用构造函数
  • 我想为每个变量设置数据
  • 再一次,For/Each 用于迭代集合中的项目。 TExperience 不是集合

标签: vb.net class for-loop each


【解决方案1】:

你所要求的是不可能的。正如您所知道的,For Each 用于对可枚举列表中的每个项目执行相同的操作。对象的属性不是可枚举列表,因此For Each 在这种情况下不适用。设置多个属性值的方法和你现在做的一样。

也就是说,在刚刚创建的对象上设置多个属性时,您可以使用对象初始化器语法,例如

Dim D As New TExperience With
{
    .CompanyName = "Any Data",
    .Country = "Any Data",
    .ID = "Any Data",
    .JobTitle = "Any Data",
    .Months = "Any Data"
}

显然不是您所要求的,但仍然比您现在正在做的事情有所改进。或者,如果对象需要所有数据,最好声明一个带有适当参数的构造函数,这样,调用必须提供数据。不过,您仍然需要在构造函数中单独设置每个属性。

【讨论】:

  • 当没有明确的问题涉及时,我看不出这与任何事情有什么关系。为什么要花时间重新表述上面的 cmets,因为它没有为您提出的解决方案带来任何价值,因为您明确表示这不是他所要求的。 IMO 首先要求澄清......另一方面,使用 with 进行实例化很好,但同样是逐案,我们显然不知道那是什么。
  • @Zaggler,我认为很明显 OP 认为将多个属性设置为一个列表,并且他们想要一种枚举该列表的方法。我认为提供有关如何更好地设置这些属性值的信息是值得的。
【解决方案2】:

是的,如果...
注意:您发布的课程包含公共字段,例如Public CompanyName As String。虽然使用属性通常是个好主意 - Public Property CompanyName As String。下面的代码用于类属性,但您可以将PropertyInfo 替换为FieldInfo。但是,建议使用属性来公开类值。

如果您正在寻找问题的是/否答案,可以通过 for-each 设置属性吗?,答案是 。但是应该出现更多关于您的问题的问题。 何时、为什么、为了什么……

例如,我们遇到特定类型与其他类型具有共同属性的情况,有时甚至是从这些类型派生的,我们需要对其进行转换。一种方法是使用“装饰器”模式。但这是我们为水合属性所做的事情(免责声明 - 代码是通过转换器从 c# 转换的,我添加了一些“作为类型”之类的内容,我不确定它是否 100% 正确)

''' Everything "S" - source, "D" - destination. "T" - type
Public Shared Function Hydrate(Of TS, TD)(source As TS, destination As TD) As TD

    Dim sPI() As PropertyInfo = 
        source.[GetType]().GetProperties(BindingFlags.[Public] Or BindingFlags.Instance)
    Dim dPI() As PropertyInfo = 
        destination.[GetType]().GetProperties(BindingFlags.[Public] Or BindingFlags.Instance)

    For Each s As PropertyInfo In sPI
        Dim d As PropertyInfo = 
            dPI.FirstOrDefault(Function(pi) pi.Name = s.Name AndAlso pi.PropertyType = s.PropertyType)
        If d IsNot Nothing Then
            d.SetValue(destination, s.GetValue(source, Nothing), Nothing)
        End If
    Next
    Return destination
End Function

那么,我们开始吧。在此示例中,属性被迭代,当它们的名称和数据类型完全匹配时,它们被填充。但是除了类似型号的补水,它还有什么用呢?我的意思是,当 JSON 被反序列化等时,这就是内部发生的事情。但在日常编程中,你不会做这样的事情。

【讨论】:

  • 请注意,此代码不适用于 OP 类,因为该类没有任何属性。 GetProperties 不会在 OP 类上返回任何内容。
  • ...我也 认为 OP 想要从 Arr 函数中迭代成员名称
  • @ChrisDunaway 嘿,很明显......我正在回答这个问题,不管 OP 代码如何。问题是“...迭代类属性”
  • @Plutonix 见上文^^
  • 不要吹毛求疵 - 这是一个足够有用的答案 - 但 properties 由于您的编辑而被添加到问题中; OP从未提及它。我认为 OP 不知道字段和流之间的区别
猜你喜欢
  • 2015-06-19
  • 2015-05-21
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 2016-04-18
  • 2011-01-10
  • 2015-06-02
  • 2019-01-12
相关资源
最近更新 更多