【问题标题】:How can I assign multiple object properties at once in C#?如何在 C# 中一次分配多个对象属性?
【发布时间】:2018-10-15 17:15:35
【问题描述】:

背景

我有一些来自DataGridView 的行,我将它们转换为实体对象。在转换过程中,我重置了一些值。由于“基本”数据来自当前DataGridViewRowDataBoundItem,因此使用对象初始化器 不是我正在寻找的选项,我不这样做'不想再次分配从DataBoundItem 转换的第一个对象的每个值(冗余)。

所以我的问题是:是否可以一次分配多个对象属性?如果可以,如何实现?

研究

我发现了以下问题,但都没有解决我的问题:

Assigning multiple variables at once in c#

Assign multiple variables at once

Setting multiple properties with one declaration in Windows Forms (C#)

代码

foreach (DataGridViewRow CurrRow in DataGridView.Rows)
{
    SomeObject SomeObj = (SomeObject) CurrRow.DataBoundItem;
    SomeObj.PropertyA = 0;
    SomeObj.PropertyB = 0;
    SomeObjCollection.Add(SomeObj);
}

我尝试过的

用逗号分隔要分配的属性(在逗号处给出语法错误):

TimeEntries.Hours, TimeEntries.Expenses = 0;

【问题讨论】:

  • 多个 = 语句有什么问题?

标签: c#


【解决方案1】:

您可以使用= 运算符将它们分配到一个链中:

TimeEntries.Hours = TimeEntries.Expenses = 0;

好像你会倒着读这句话。

在您的循环中,它看起来像这样:

foreach (DataGridViewRow CurrRow in DataGridView.Rows)
{
    SomeObject SomeObj = (SomeObject) CurrRow.DataBoundItem;
    SomeObj.PropertyA = SomeObj.PropertyB = 0;
    SomeObjCollection.Add(SomeObj);
}

重要提示:

如果您正在处理引用类型,这将只为不同的属性分配 1 个引用。因此,更改其中一个会影响所有其他属性!

【讨论】:

  • 谢谢!这正是我想要的!
  • @chade_ 不客气,在使用引用类型时要注意! intdouble 等可以正常工作,但引用类型的属性将不再独立!我对我的回答做了补充。
  • 它在我的情况下有效,所以我似乎没有使用引用类型。
【解决方案2】:

元组解构:

(TimeEntries.Hours, TimeEntries.Expenses) = (0, 0);

【讨论】:

    【解决方案3】:

    此答案旨在作为规范来显示设置值的两种方式。

    answer by Mong Zhu 中解释的第一个选项是简单地链接 = 运算符:

    int a, b;
    a = b = 0;
    

    但关键在于,如果您使用引用类型,则只会分配一个引用。在这种情况下,使用元组解构的answer from Dennis_E 将起作用:

    int a, b;
    (a, b) = (0, 0);
    

    重要提示:要运行后面的代码,您要么需要compiling on .NET 4.7 or higher。如果您运行的是 .NET 4.6.2 或更低版本,请通过在包管理器控制台中运行以下命令来安装 NuGet 包 System.ValueTuple

    Install-Package "System.ValueTuple"
    

    【讨论】:

      【解决方案4】:

      不,不可能,C#没有with statement

      【讨论】:

        【解决方案5】:

        一种解决方案是在每个阶段使用新对象。 不用设置属性,而是生成一个新对象,即LINQ Select。 然后,您可以使用Constructor and/or Object Initialization

        每个阶段可以有 2 种不同的类型。

        // Using LINQ
            SomeObjCollection.AddAll(DataGridView.Rows
                .Select(currRow => new SomeObject(CurrRow.DataBoundItem)
                {
                      PropertyA = 0;
                      PropertyB = 0;
                });
        
        // Using yield (I'd use LINQ personally as this is reinventing the wheel)
        // But sometimes you want to use yield in your own extension methods
        IEnumerable<SomeObject> RowsToSomeObject()
        {
            foreach (var currRow in DataGridView.Rows)
            {
                yield new SomeObject(CurrRow.DataBoundItem)
                {
                      PropertyA = 0;
                      PropertyB = 0;
                }
            }
        }
        // and then later in some method:
        SomeObjCollection.AddAll(RowsToSomeObjects())
        

        虽然这在技术上可能不是您所要求的,但它是您在使用该概念的语言中可能习惯的另一种模式。

        我建议学习 map/reduce(选择/聚合)习语,因为它们通常 比传统的循环和面向副作用的代码更适合数据处理,在这些代码中你不断地改变同一个对象。

        如果此操作是中间操作,那么您可以只使用匿名对象,直到您获得最终的返回数据类型。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-01-29
          • 2022-11-10
          • 2017-09-12
          • 1970-01-01
          • 1970-01-01
          • 2020-01-24
          • 2020-04-21
          相关资源
          最近更新 更多