Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
958 views
in Technique[技术] by (71.8m points)

initialization - C# initialize get only list propetry with dynamic range of objects

I have the following object declaration:

    DatabaseTableElm exportTable = new DatabaseTableElm()
    {
        Columns =  columnCt ,
        Keys = { 
            new DatabaseKeyCt()
            {
/* this way of setting columns  works */
                Columns = { new DatabaseKeyColumnCt() { Name = "ObjectId", SortOrder = SortOrderEnum.Descending } }, 
                Type = DatabaseKeyTypeEnum.Primary
            },
            new DatabaseKeyCt()
            {
/* this way of setting columns does not work */
                Columns =  list.Keys.Select(x => new DatabaseKeyColumnCt() { Name = x, SortOrder = SortOrderEnum.Ascending } ).ToList(),
                Type = DatabaseKeyTypeEnum.Unique
            }
        },
        Name = "test",
        Schema = "dbo",
        Temporal = true
    };

Columns is a property defined in class DatabaseKeyCt like

public List<VaultSchemaObjects.Tns.DatabaseKeyColumnCt> Columns { get; } = new List<VaultSchemaObjects.Tns.DatabaseKeyColumnCt>();

At the first comment you can see that despite being a get only property, I can still initialize it with an array of "static" values. At the second comment I try to do the same but now with a list of objects. But at that point I get an error saying that columns is readonly.

My assumption is that at the first comment the array is accepted as some kind initial collection of the list. But At the second comment it thinks I am trying to assign a new list and it fails.

I cannot change class so the solution of adding a setter to the Columns property is not valid.

Can the line at the second comment be fixed so I can populate the list from my linq expression?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

No, you cannot initialize readonly property without changing source code

TLDR; In the first case you have Collection Initializer which is actually compiled as a bunch of Add method calls on the already created collection instance. So if you have a property

public List<int> Values { get; } = new List<int>();

Property already initialized with an empty list. And when you use collection initializer on this property

Values = { 1, 2 }

It's compiled as

Values.Add(1);
Values.Add(2);

You can see the difference if you'll try to apply collection initializer to the new list and assign it to the property:

Values = new List<int> { 1, 2 } // Fails as your second attempt

This problem can be solved with Init Only Setters which are not yet implemented (as far as I know). And the solution will be:

public List<int> Values { get; init; }

But as you cannot change source code, all you can do is manually add items to the read-only property (i.e. do the job of collection initializer).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...