-6

How can I use the curly braces from object constructor when modifying an existing instance?

I tried shallow and deep-copying in the constructor, but there doesn't seem to be a way to swap out this with the desired object instance, or a simple and reliable way to set all of the (ever-changing during development) fields and properties inside the constructor.

As you can see here, curly braces save a lot of space compared to the old get { return ... } way:

public static MyClass MyClass1 => new MyClass()
{
    Property1 = 20,
    Property2 = "some text",
    Property3 = new MyOtherClass(MyEnum.Something)
};

Basically the same code but with extra 5 lines:

public static MyClass MyClass2
{
    get
    {
        var instance = new MyClass(); // or it could be  = MyClass1;
        instance.Property1 = 42;
        instance.Property2 = "some other text";
        instance.Property3 = new MyOtherClass(MyEnum.SomethingElse);
        return instance;
    }
}

My goal is to use the curly braces to set new property values of a base object (without inheritance or manually doing a shallow/deep copy in the constructor) to save all that vertical space. How can I do that?

I'm using full document auto-formatting often, so manually formatting the code and just not touching it is not going to work.

The issue I am trying to solve: get { ... } -style getter is taking up 5 extra lines of code when auto-formatted. => - style getter is much more compact, and I want to find a way to use it instead.

user1306322
  • 8,561
  • 18
  • 61
  • 122
  • 4
    I don't get the issue you are trying to solve. – Patrick Hofman Mar 08 '17 at 11:15
  • removing extra 5 lines of code to save vertical space, it's right in the body of my question, man – user1306322 Mar 08 '17 at 11:16
  • *My goal is to use the curly braces to set new property values of a base object*. How are you using curly braces? They are just an indicator for code blocks, right? What is wrong with your first code block then? – Patrick Hofman Mar 08 '17 at 11:18
  • No. I think you may not be aware of the useful feature of curly braces for setting values in instance constructors. Look it up, it's a cool thing. [Example](https://stackoverflow.com/questions/5146588/in-c-how-to-access-curly-brace-constructor-using-reflection) – user1306322 Mar 08 '17 at 11:19
  • Curly braces aren't a feature. – Patrick Hofman Mar 08 '17 at 11:19
  • @user1306322 you are not clearly explaining what it is you want. It is unclear what you're asking. Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the [How to Ask](http://stackoverflow.com/help/how-to-ask) page for help clarifying this question. – Nkosi Mar 08 '17 at 11:20
  • when you say "curly braces" do you mean Lambdas (anonymous functions) ? – Dave Becker Mar 08 '17 at 11:21
  • How am I not explaining? I said I want to save 5 lines of code by utilizing curly braces which isn't impossible unless it's used with a constructor of a new object. And I want to use them somehow, but to modify the properties of an existing object. – user1306322 Mar 08 '17 at 11:21
  • 2
    I suppose then the answer is "you can't". – Matthew Watson Mar 08 '17 at 11:22
  • @DaveBecker I mean the curly braces like in object constructor, [where you can set its properties right after initialization](https://stackoverflow.com/questions/5146588/in-c-how-to-access-curly-brace-constructor-using-reflection). It's been a feature of c# since version 3. – user1306322 Mar 08 '17 at 11:23
  • @MatthewWatson maybe, but what about maybe somebody knows the answer and you don't? Please don't tell me the fact that one person doesn't know makes it an invalid question. I'm looking for perhaps a way to initialize an object and inside the initializer to copy the values of another instance. Perhaps somebody knows. – user1306322 Mar 08 '17 at 11:24
  • "curly braces" works only with constructor – Fabio Mar 08 '17 at 11:24
  • You can consider move to the `vb.net` where `With` block doing exactly what you trying to achive – Fabio Mar 08 '17 at 11:26
  • Possibly [`AutoMapper`](http://automapper.org/) can help... – Matthew Watson Mar 08 '17 at 11:29
  • @Fabio moving the whole project from c# to vb is not an option. Saving vertical space is not worth that much effort. – user1306322 Mar 08 '17 at 11:29
  • @MatthewWatson automapper returns an instance, and doesn't allow the curly brace usage because it wouldn't be a constructor. – user1306322 Mar 08 '17 at 11:30
  • 1
    @user1306322, ah now I get it. You are referring to "Object Initialisers" (https://msdn.microsoft.com/en-us/library/bb384062.aspx) and as the name suggests, they are only for initialisation. – Dave Becker Mar 08 '17 at 11:34
  • @DaveBecker right, so how do I get to initialize a new object with an existing object's values and then change some more values inside the curly braces? That's the real question here. – user1306322 Mar 08 '17 at 11:40
  • 1
    I suppose you could add the object to the constructor and copy it's values and then the new values would be picked up from the initialiser. – Dave Becker Mar 08 '17 at 11:42
  • Yes, but I'd like to be able to do it automatically, kinda like how the `this.MemberwiseClone()` returns a shallow copy in just 1 short method call, but that returns an instance, and I can't set `this` to an instance inside the initializer or return that new instance, because that's not how initializers work. And manually copying the properties into `this` is not an option because there are way too many different properties and fields to update every time something changes. Maybe there is some way to alter values of `this` through reflection. – user1306322 Mar 08 '17 at 11:46
  • Just deleted my answer after I just saw, "And manually copying the properties into `this` is not an option because there are way too many different properties". Sorry, can't help. – Dave Becker Mar 08 '17 at 11:53

2 Answers2

0

Figured it out:

public class MyClass
{
    public MyClass() { }
    public MyClass(MyClass baseInstance)
    {
        var fields = typeof(MapObject).GetFields();
        foreach (var field in fields)
            field.SetValue(this, field.GetValue(baseInstance));

        var props = typeof(BaseItems).GetProperties();
        foreach (var prop in props)
            if (prop.CanWrite)
                prop.SetValue(this, prop.GetValue(baseInstance));
    }
}

… lets you do this:

public static MyClass MyClass2 => new MyClass(MyClass1)
{
    Property1 = 42,
    Property2 = "some other text",
    Property3 = new MyOtherClass(MyEnum.SomethingElse)
};

It's not ideal but it works for me.

user1306322
  • 8,561
  • 18
  • 61
  • 122
-2

Are you trying to use property?

class MyClass()
        {
            private int myInt;

            public int MyInt { get; set; }
        }
maximelian1986
  • 2,308
  • 1
  • 18
  • 32
  • No, I don't think you understood the issue here. – user1306322 Mar 08 '17 at 11:25
  • You may create constructor overload that take as parameter another instance of that object. – maximelian1986 Mar 08 '17 at 11:27
  • Yea, that's what I was thinking, but then copying over the ever-changing properties and fields manually is a real hassle. Automatic cloning doesn't seem to be working like that, because it returns an instance and you can't set `this` to another instance in the constructor. Maybe there is some way, but I just don't know about it yet. – user1306322 Mar 08 '17 at 11:32