Grasshopper

algorithmic modeling for Rhino

What is the best way to manage Lists on Custom Classes

I have a list of a custom class (panels) and each instance has a list of parts (another custom class). I want to add some parts to that list, then return the new panel with all its parts (new and old). For read access, I am exposing the parts list as a property with a backer field using {get}.

To provide writing capability, I am thinking that there are probably three possible routes, and am wondering what a more experienced programmers would say is the "correct" way..

1) Add a {set} method to the property that would .Add to the list

2) Add a {set} method that overwrites the list entirely, (meaning anytime it is used, I would first call {get} then perform manipulation in the code that called it, then completely override the old list with a new one.

3) Only allow the list to be set on construction of the class, so that each time the list needs to change, I would copy the class and feed the constructor an updated list. I've read in a few places to be careful and make sure to create copies rather than change originals... Is that necessary in this situation?

I am leaning towards method 2 or 3, as I also have a Dictionary property that I want to be able to modify, and don't want to get into crazy complicated Indexers and such.

I welcome people's thoughts and comments, thanks!

Views: 332

Attachments:

Replies to This Discussion

Personally I've become a huge fan of making as many types immutable as possible. There's plenty of immutable collection classes in the .NET framework these days to help with that, but you can also choose to make stuff immutable from scratch. Admittedly it does get difficult for really complicated types, especially if you want to keep copying to a minimum, and, admittedly, C# doesn't seem to 'like' dealing with immutable types. Its syntax was clearly designed for get/set modifications.

If your panel class is already immutable (or if you would like to make it so) then option (3) is the one to go for. You can still have a method which adds elements to a panel, but that method must now return a new instance of the panel while leaving the original intact. Even though C# doesn't appreciate this approach, Grasshopper very much does, as it demands that data is duplicated anyway every time it is modified in some way.

If on the other hand your type is mutable, then there are fairly clear .NET guidelines with respect to collections. You can expose a collection (say List<Part>) via a getter property. The caller then has the option to call Clear(), Add(), AddRange(), Remove(), RemoveRange(), RemoveAt(), etc. etc. on that collection and modify it as they see fit. I think it's a bad idea to allow them to set a new List<Part>, you want to expose as few internal fields as possible. It is still pretty trivial to just replace the entire collection, just by calling Clear() and AddRange() on the existing collection.

You can also choose to create your own Part collection class if you want more control over how it's modified. I recommend against putting collection modifiers on the top level class though. I.e. don't do this:

public class Panel

{

  public List<Part> Parts { get; }

  public bool AddPart(Part newPath)

  {

    ...

  }

}

but instead allow people to add panels through the collection type returned via the Parts property.

To add some more example code, I'd expect this to work as follows inside the Component class.

For immutable panel types:

Panel panel = null;

Part part = null;

if (!DA.GetData(0, ref panel)) return;

if (!DA.GetData(1, ref part)) return;

// the Add() method on the Parts collection returns a NEW panel.

panel = panel.Parts.Add(part); 

DA.SetData(0, panel);

For mutable types:

Panel panel = null;

Part part = null;

if (!DA.GetData(0, ref panel)) return;

if (!DA.GetData(1, ref part)) return;

// the panel must be duplicated manually in this case.

panel = panel.DuplicatePanel();

panel.Parts.Add(part);

DA.SetData(0, panel);

I think I'm going to go full immutable, it seems easier to program the duplication behavior into the class, instead of worrying about manually creating a copy every time.

Thanks!

RSS

About

Translate

Search

Photos

  • Add Photos
  • View All

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service