Search code examples
c#return-valuemethod-chaining

How to hop between inner class returns when creating a new variable with chaining methods c#


I don't know if hopping is the best word for what i want to achive (because i never learnt programming officially) basically i have a class with two inner classes here is the code

using System.Drawing;

namespace Leveltar_Fresh
{
   class Scene
   {
      private Image image;

      public class Sphere : Scene
      {
          public Sphere()
          {
            
          }

          public Sphere addClickable(int x, int y, int r)
          {
             Clickable clickable = new Clickable.Sphere(x, y, r);
             return this;
          }
      }

      public class Rectangle : Scene
      {
         public Rectangle()
         {

         }

         public Rectangle addClickable(int x, int y, int width, int height)
         {
            Clickable clickable = new Clickable.Rectangle(x, y, width, height);
            return this;
         }
      }

      public static Scene createNewScene(Scene scene)
      {
         return scene;
      }
   }
}

i tried adding a method to the outer class which i can use as another chain for my method chain this method

public static Scene getScene()
{
   return this;
}

but when i called this method in a chain i couldn't access the inner classes i did new Scene.Sphere().addClickable(20, 20, 50).getScene() and then i couldn't call neither of the inner classes i have more experience with java and i know there are some differences between the usage of inner classes in c# and java but what causes this and how can i fix this?


Solution

  • I'm not sure I understand what you are trying to do. However, the reason why you can't access the nested classes after calling the getScene() method is because the scope of your nested classes is limited to within the parent class only.

    In response to my comment Do the classes need to be nested, you mentioned you only needed it for code organisation and not limiting scope and so I would advise to move those classes out. This will in fact result in cleaner code.

    Below I have attempted to retain your functionality and simply make your code a bit more fluent.

    public class Scene
    {
        public Scene()
        {
             ChildSphere = new Sphere();
             ChildRectangle = new Rectangle();
        }
    
        // 2 previously nested classes are now public properties.
        public Sphere ChildSphere { get; }
        public Rectangle ChildRectangle { get; }
    
        public static Scene CreateNewScene(Scene scene)
        {
            //logic...
            return scene;
        }
    
        public Scene GetScene()
        {
            return this;
        }
    }
    
    public class Sphere : Scene
    {
        public Sphere AddClickable(int x, int y, int r)
        {
            Clickable clickable = new Clickable.Sphere(x, y, r);
            // logic..
            return this;
        }
    }
    
    public class Rectangle : Scene
    {
        public Rectangle AddClickable(int x, int y, int width, int height)
        {
            Clickable clickable = new Clickable.Rectangle(x, y, width, height);
            // logic..
            return this;
        }
    }
    

    Which results in this:

    new Scene().ChildSphere
    .AddClickable(20, 20, 50)
    .GetScene()
    .ChildRectangle
    .AddClickable(20,40,60,80)
    .GetScene();
    

    I have included the GetScene() method only because you had it in your example. I don't think its of much use given the code you provided.

    Something to point out is in the example above, once you call this new Scene().ChildSphere you no longer have access(via chaining) to the original(very first) scene. In other words every additional chain will be returning the current instance at that point.

    So in terms of objects returned after each chain we have:

    new Scene().ChildSphere     // scene1 -> scene1.ChildSphere
    .AddClickable(20, 20, 50)   // scene1.ChildSphere
    .GetScene()                 // scene1.ChildSphere
    .ChildRectangle             // scene1.ChildSphere.ChildRectangle
    .AddClickable(20,40,60,80)  // scene1.ChildSphere.ChildRectangle
    .GetScene();                // scene1.ChildSphere.ChildRectangle
    

    If you want at any point to get back to scene1 or some other previous parent then you'll need to implement a way of linking parent and child. It is possible but have excluded this as out of scope for this question.