3

Background

I have some rows from a DataGridView that I convert to entity objects. In the conversion process I reset some values. As the "basic" data comes from the DataBoundItem of the current DataGridViewRow, using object initializers is therefore not the option i'm looking for and I don't wan't to assign every value from the first object casted from DataBoundItem again (redundancy).

So my question is: Is it even possible to assign multiple object properties at once and if, how do you achieve it?

Research

I found the following questions, but none of them are solving my problem:

Assigning multiple variables at once in c#

Assign multiple variables at once

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

Code

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

What I have tried

Seperate the properties to assign with comas (Gives a syntax error at the coma):

TimeEntries.Hours, TimeEntries.Expenses = 0;
Filnor
  • 1,290
  • 2
  • 23
  • 28

5 Answers5

5

you can assign them in a chain using the = operator:

TimeEntries.Hours = TimeEntries.Expenses = 0;

as if you would read this statement backwards.

In the case of your loop it would look like this:

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

Important note:

If you are dealing with reference types this will assign only 1 reference to different properties. So that changing one of them will affect all other properties!

Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
  • Thank you! This is exactly what i was looking for! – Filnor Aug 30 '17 at 13:00
  • @chade_ you are welcome, be aware when using this with reference types! `int` and `double` and so on will work without problems, but properties of reference types will not be independent anymore! I made an addition to my anwer. – Mong Zhu Aug 30 '17 at 13:05
  • It worked in my case, so it's seems i'm not using reference types. – Filnor Aug 30 '17 at 13:08
3

Tuple deconstruction:

(TimeEntries.Hours, TimeEntries.Expenses) = (0, 0);
Dennis_E
  • 8,751
  • 23
  • 29
2

This answer is intended as a canonical to show both ways of setting the values.

The first option as explained in the answer by Mong Zhu is to simply chain the = operator:

int a, b;
a = b = 0;

But the crux in this is the fact that if you are working with reference types, only one reference will be assigned. In that case, the answer from Dennis_E, which uses tuple deconstruction, would work:

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

Important note: To run the latter code you either need to be compiling on .NET 4.7 or higher. If you are running .NET 4.6.2 or lower, install the NuGet package System.ValueTuple by running this command in your package manager console:

Install-Package "System.ValueTuple"
Filnor
  • 1,290
  • 2
  • 23
  • 28
1

No, it is not possible, C# has no with statement

Haukinger
  • 10,420
  • 2
  • 15
  • 28
  • C# has a with statement now and it might work in cases like the poster's, but it produces a copy of the object: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/with-expression – Froggy Aug 09 '22 at 09:20
  • Doesn't work with classes right now, though, and might never will (because of copying). – Haukinger Aug 09 '22 at 13:38
0

One solution would be to use new objects at each stage. Instead of setting properties, yield a new object, i.e. LINQ Select. Then, you can use a Constructor and/or Object Initialization

You can have 2 different types for each stage.

// 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())

While this might not technically be what you asked, it's an alternative pattern to what you might have been used to in language with that concept.

I recommend learning about map/reduce (Select/Aggregate) idioms, as they usually are better suited at data processing than traditional loops and side-effect oriented code where you keep mutating the same object.

If this operation is intermediary, then you can just use Anonymous Objects until you get to your final return data type.

Novaterata
  • 4,356
  • 3
  • 29
  • 51