0

As much as I agree with downvoting a crappy question, is it really that bad to have a(nother) resource noting that the below compile essentially identically?

Is there a way to tell whether a property is being set like this

MyClass myClass = new MyClass() { Value = 5 };

or this

MyClass myClass = new MyClass();
myClass.Value = 5;

?

In my application, I need to use would prefer to use object initializer syntax, but I also need setter logic that only occurs during object construction.

I assume the answer is no, as (to my knowledge) the first is essentially a shortcut for the second. But otherwise I'll have to put logic in the setter that should only ever run once or change my initialization syntax — neither of which sound attractive.

Sinjai
  • 1,085
  • 1
  • 15
  • 34
  • 2
    Compile both versions and compare the IL code – Thomas Weller Jul 10 '17 at 14:26
  • @ThomasWeller Good call, deleting this... – Sinjai Jul 10 '17 at 14:27
  • 2
    The put the logic for 'it has been set in the ctor' right in the ctor. – ckruczek Jul 10 '17 at 14:27
  • @ThomasWeller On second thought, undeleting, but editing question to ask for a workaround (I assume this is valid in a question?). – Sinjai Jul 10 '17 at 14:29
  • You can use the initializer only if you have a setter defined. – MakePeaceGreatAgain Jul 10 '17 at 14:30
  • 1
    Those are basically the same thing, just different syntax (both call the getter of the property). You could have a constructor that takes the value instead and then you'd know when it was set during construction vs after construction. – juharr Jul 10 '17 at 14:33
  • @juharr Of course. The only problem is, I have classes with 10 or more properties, and object initialization syntax is much clearer for the developer. Also, I'd have to go back and change a bunch of constructor calls... – Sinjai Jul 10 '17 at 14:35
  • Can you give an example of the problem? As another question perhaps. Clearly state what you have now and what doesn't work. That will make more sense than asking for workaround to workaround, as you seems to me doing now. What exactly logic to run? What is the problem with running it in the constructor? Do you want to set some properties via object initializer and **then** run initialization logic or what? – Sinatr Jul 10 '17 at 15:45
  • @Sinatr Just not sure what I'd title that. – Sinjai Jul 10 '17 at 16:28
  • @S.Akbari Good suggestion, I'll do just that. – Sinjai Jul 11 '17 at 15:01

2 Answers2

2

There is no difference at all. Check the underlying IL:

// Code size       30 (0x1e)
.maxstack  3
.locals init ([0] class MyProj.MyClass myClass,
              [1] class MyProj.MyClass myClass2)
IL_0000:  nop
IL_0001:  newobj     instance void MyProj.MyClass::.ctor()
IL_0006:  dup
IL_0007:  ldc.i4.5
IL_0008:  callvirt   instance void MyProj.MyClass::set_Value(int32)
IL_000d:  nop
IL_000e:  stloc.0
IL_000f:  newobj     instance void MyProj.MyClass::.ctor()
IL_0014:  stloc.1
IL_0015:  ldloc.0
IL_0016:  ldc.i4.5
IL_0017:  callvirt   instance void MyProj.MyClass::set_Value(int32)
IL_001c:  nop
IL_001d:  ret

That is generated for below code:

MyClass myClass = new MyClass() { Value = 5 };
MyClass myClass2 = new MyClass();
myClass.Value = 5;

The object initializers are just syntactic sugar and they are created to simplify construction of objects when you're using an object.

However you can check the following post to see the benefit of using an Object Initializer :

Is there any benefit of using an Object Initializer?

Salah Akbari
  • 39,330
  • 10
  • 79
  • 109
0

You can use the initializer only if you have a setter defined. It is just a simplification for this:

var m = new MyClass();
m.MyInt = 3;

Apart from this you shouldn´t rely on this at all, you should however ensure that your setter is actually doing the right things (e.g. validate the new value). However when you want to ensure the property is only set during initialization why not use a readonly-property:

class MyClass
{
    privarte readonly int _myInt;
    public int MyInt { get { return this._myInt; } }
    public MyClass(int theValue) 
    {
        this._myInt = theValue; 
    }
}

Now you can only instantiate your class as follows:

var m = newMyClass(3);

making all worries about if the setter was called or if it even exist obsolete.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111