3

There's a syntax in C# that I discovered recently that enables you to initialize a read-only collection during initialization:

class Foo
{
    public List<Bar> Bars { get; } = new List<Bar>();
}

var foo = new Foo
{
    Bars = 
    {
        new Bar()
    }
}

Which is great as it leads to very expressive code. But I have a situation where I already have a collection of Bar, and I want to initialize it using this syntax (even though Bars is readonly). Is there a way to do this?

var bar = new List<Bar>();
var foo = new Foo
{
    Bars =  bar // error: Property or indexer Foo.Bar cannot be assigned to -- it is read only
}
13
  • 1
    If you could change Foo, you can simply add a constructor that takes List<Bar> as an argument - var foo = new Foo(bar); Commented Jan 30, 2019 at 13:03
  • 1
    Allow the Foo constructor to take Bar as a parameter and change to this public List<Bar> Bars = { get; private set; } Commented Jan 30, 2019 at 13:05
  • Either add a setter or a constructor. It's a difference whether you assign it inline in the class(which is allowed without setter) or from outside. Commented Jan 30, 2019 at 13:07
  • 1
    @LeonardoSeccia private set; is useful in c#5, but in c#6 you can have read-only properties by only specifying {get;}. Commented Jan 30, 2019 at 13:08
  • @LeonardoSeccia private set will work from outside the Foo ? Commented Jan 30, 2019 at 13:09

1 Answer 1

3

I want to initialize it using this syntax (even though Bars is readonly)

You simply cannot.

As we are using the initializer syntax and it actually call the setter method aka set of the property and you have a readonly property which can only be set by the class itself and for setting it form outside the class we need to pass it via constructor of Foo while creating it's instance.

UPDATE:

The first example code actually ends up call to Add method of the List<T>. It will compiled to following code:

 Foo foo = new Foo();
 foo.Bars.Add(new Bar());

While you can add new items to the Bars but you cannot change it's reference to point to a different object directly using the initializer due to read-only property while it's totally legit to call the member method of List<Bar> on the instance like Remove, Find etc.

Sign up to request clarification or add additional context in comments.

5 Comments

Actually, a get only property is not only readonly, it's immutable - you can only set it's value in the constructor of the type.
It's what I expected, but ... do you know how the other example (the one initializing it directly) works? My guess is that under the hood it's calling the .Add member of the collection.
@BrunoBrant can you provide that in a fiddle as working example ?
@BrunoBrant you are correct, it internally converts it to Add method call.
From C# 9.0 onwards, you can use { get; init; } to enable assigning at initialization time, i.e. new Foo { Bars = something } will work, but var foo = new Foo(); foo.Bars = something; will not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.