简体   繁体   中英

Setting a property on 'value' in 'set' auto-property on class property

I have two classes that need to know about each other.

In my example, I am using a House with Rooms.

The House needs to know about the Rooms, and the Rooms need to know about the House.

I currently have a setup where I do something similar to this in my mapping:

var house = new House();
var room = new Room(house);
house.Rooms.Add(room);

By doing this, I am linking the House to the Room and the Room to the House.

I was wondering, is it bad practice to do the following?

private House house;
public House House
{
    get
    {
        return house;
    }
    set
    {
        house = value;
        value.Rooms.Add(this);
    }
}

This way, whenever a room is created, it will automatically be added to the houses list of rooms.

If this is bad practice, what other alternatives do I have?

Thanks.


Edit. (Reasoning)

The reason I am doing this is because I am creating multiple types of output objects, and these different output objects require different answers.

The calculations I am doing can take a lot of time, so I want them to only calculate what they need to.

By having the two classes aware of each other, I am about to call a property on Room which needs input from House, and it will only get calculated when I actually need it.

Eg

public class Room {
    public House House { get; set; }
    public double Size { get; set; }

    public double GetSizePercent() 
    {
         return Size / House.TotalSize;
    }
}

In my real world application, there are a lot more properties that would be accessed from the House class, in this example, and other classes would also need to know about House.TotalSize.

Also, on House, I may need to iterate over all of the Rooms that belong to it to perform other calculations.

I hope this is clear, if not, I can try elaborate more.

Thanks again.

I would consider using a side-effect of setting the House property for adding it the collection to be a bad practice. A property setter should set the property. Causing it to do something unrelated, such as adding the object to a collection, makes for very unreadable code when someone else is trying to follow it later.

I would do something like this:

public class House {
    public House() {        
        Rooms = new List<Room>();
    }
    public Room CreateRoom() {
        Room result = new Room(this);
        Rooms.Add(result);
        return result;
    }
    public List<Room> Rooms { get; private set; }

    public class Room { 
        public Room(House house) {
            this.House = house;
        }
        public House { get; private set; }  
    }
}

Typically, I would also want to prevent code from using my class incorrectly-- such as creating a room linked to a House but forgetting to add it to Rooms, or adding it to Rooms but setting the House property incorrectly. To fix that, I would implement something like this:

public class House {
    private List<Room> rooms;
    public House() {
        rooms = new List<Room>();
        Rooms = new ReadOnlyList<Room>(rooms);
    }
    public Room CreateRoom() {
        Room result = ((IRoomFactory)Room.Factory.Instance).Create(this);
        rooms.Add(result);
        return result;
    }
    public ReadOnlyList<Room> Rooms { get; private set; }

    private interface IRoomFactory {
        Room Create(House house);
    }

    public class Room { 
        public class Factory : IRoomFactory {
            public static readonly Factory Instance = new Factory();
            Room IRoomFactory.Create (House house) {
                return new Room(house);
            }
        }
        private Room(House house) {
            this.House = house;
        }
        public House { get; private set; }  
    }
}

Then, when you want to add a room to your house, you would simply call

var house = new House();
var room = house.CreateRoom();

Now you can't create a room from anywhere outside the House class, nor can you add rooms to the Rooms collection of the class from outside. The only way to do either is from within House, and it takes care of the linking and adding all at once through the CreateRoom() method.

This is bad practice and I highly recommend against it. Always try to have objects point only in one direction of dependency to each other. There are really efficient ways to make this work but as for having both objects aware of each other I would suggest against it. If you agree, which you may not, then add a little more code showing why the room needs to know about the house and vice-versa and I'll give you code formatted as simple as possible in the way I feel you would appreciate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM