Readonly field in object initializer

2019-06-16 09:56发布

I wonder why it is not possible to do the following:

struct TestStruct
{
    public readonly object TestField;
}

TestStruct ts = new TestStruct {
    /* TestField = "something" // Impossible */
};

Shouldn't the object initializer be able to set the value of the fields ?

标签: c# readonly
7条回答
可以哭但决不认输i
2楼-- · 2019-06-16 10:02

This is not possible. since readonly fields cannot be assigned from other than Constructor or Field Initializer.

What you show is actually object initializer. It is just a syntatic sugar, gets comiled into something like this

TestStruct ts;
TestStruct ts1 = new TestStruct();
ts1.TestField = value;
ts = ts1;

Is that clear why it doesn't compile?

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-06-16 10:06

I wonder why it is not possible to do the following:

Because the compiler cannot know for sure that the following code will be executed:

TestStruct ts = new TestStruct 
{
    TestField = "something"
};

You should initialize readonly members directly inline or inside the constructor.

查看更多
成全新的幸福
4楼-- · 2019-06-16 10:10

Object Initializer internally uses a temporary object and then assign each value to the properties. Having a readonly field would break that.

Following

TestStruct ts = new TestStruct 
{
     TestField = "something";
};

Would translate into

TestStruct ts;
var tmp = new TestStruct();
tmp.TestField = "something"; //this is not possible
ts = tmp;

(Here is the answer from Jon Skeet explaining the usage of temporary object with object initalizer but with a different scenario)

查看更多
forever°为你锁心
5楼-- · 2019-06-16 10:11

From MSDN:

The readonly keyword is a modifier that you can use on fields. When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.

So it's simply not (yet) possible since object initializers are just post-creation assignments.

查看更多
疯言疯语
6楼-- · 2019-06-16 10:12

I ran across an interesting "exception" to this, in the case where the readonly field extends CollectionBase.

Here's the code:

using System.Collections;

namespace ReadOnly
{
    class Program
    {
        static void Main(string[] args)
        {
            Foo foo1 = new Foo()
            {
                Bar = new Bar()  // Compile error here - readonly property.
                {
                    new Buzz() { Name = "First Buzz" }
                }
            };

            Foo foo2 = new Foo()
            {
                Bar = // No Compile error here.
                {
                    new Buzz { Name = "Second Buzz" }
                }
            };
        }
    }

    class Foo
    {
        public Bar Bar { get; }
    }

    class Bar : CollectionBase
    {
        public int Add(Buzz value)
        {
            return List.Add(value);
        }

        public Buzz this[int index]
        {
            get { return (Buzz)List[index]; }
            set { List[index] = value; }
        }
    }

    class Buzz
    {
        public string Name { get; set; }
    }
}

Foo1 is how I initially tried to do it (all these classes came from an external library so we didn't know at first that Bar was readonly). Got the compile error. Then accidentally I retyped it like foo2, and it worked.

After decompiling the dll and seeing that Bar extended CollectionBase, we realized that the second syntax (foo2) was invoking the Add method on the collection. So, in the case of collections, while you can't set a read only property, you can invoke the Add method, via object initializers.

查看更多
The star\"
7楼-- · 2019-06-16 10:26

readonly means that the field can only be set in the constructor (or in a field initializer). Properties specified in the object initializer are set after the constructor has returned. That is,

TestStruct ts = new TestStruct {
    TestField = "something"
};

is basically equivalent to

TestStruct ts = new TestStruct();
ts.TestField = "something";

(In a Debug build, the compiler may use a temporary variable, but you get the idea.)

查看更多
登录 后发表回答