none
Struct inside a class/Class inside a class RRS feed

  • Question

  • Hello!So I have a main class that where I would like to have other little classes(Note:I know it would be easy with inheritance but it would be too easy to fix this problem).Let's say I have a circle and the circle has a material,a radius etc.So I try to do this:

    static void Main(string[] args) { Circle circ=new Circle();

    //Trying to access a class it does't exist

    circ.Material.type="Wood"; } class Circle { class Material { public string type { get; set; } public float smoothness { get; set; } } class Basics { public int radius { get; set; } public float diameter { get; set; } } }

    But if I try to access a class it doesn't work.So i tried to create a variable inside the Circle class:

     static void Main(string[] args)
            {
                Circle circ=new Circle();
                circ.mat.type="Wood";
             }
       class Circle
        {
            class Material
            {
                public string type { get; set; }
                public float smoothness { get; set; }
    
            }
            class Basics
            {
                public int radius { get; set; }
                public float diameter { get; set; }
            }
          public Material mat;
          public Basics basic;
        }

    But it says that "Circle.Basics/Material is less accessible than field Circle.basic/mat".What does that mean?

    And than i tried to change with struct.So instead of class Basics and Material I used struct,but it says the same thing that is less accessible...

    Why is doing that and how can I make this without inheritance?

    Thank you!

    Sunday, March 25, 2018 4:41 PM

Answers

  • Hi Ax1al,

    First of all i would like to point out that i don't see the reason on doing this. That is the reason inheritance is for. After that i would tell you that both all your classes are private. You can't acces a private member from an instance. It has to be public. By setting them public you will be able to access them. But that will generate another issue. It will throw you an error saying Object reference is not set to an instance of an object. To correct that as well you will have to set the instances of material and Basics that you created inside the Circle class. Here is how your code should look like:

    public class Circle { public class Material { public string type { get; set; } public float smoothness { get; set; } } public class Basics { public int radius { get; set; } public float diameter { get; set; } } public Material mat= new Material(); public Basics basic = new Basics(); }

    Now you can access all the data you want. You could also set the instances in a Cirle constructor like so:

        public class Circle
        {
            public Material mat;
            public Basics basic;
            public Circle() 
            {
                 mat = new Material();
                 basic = new Basics();
            }
    // you could also pass data in there to set them
            public Cirlce(string type, float smoothness, ect)
            {
                mat = new Material();
                mat.type = type;
                mat.smoothness = smoothness;
                basic = new Basic();
                //etc..
            }
    
            public class Material
            {
                public string type { get; set; }
                public float smoothness { get; set; }
    
            }
            public class Basics
            {
                public int radius { get; set; }
                public float diameter { get; set; }
            }
    
        }

    I'd like to point out that there is no reason on doing this since inheritance is the easiest and best way to achieve that. Also in order to access it without a variable all the members inside the class will have to be static. So if you try to access it without creating an instance you would do it like so: Circle.Material.type but the type member has to be static in order to achieve that.

    Hope this helps you.

    Best Regards,

    Konstantinos Pap



    • Edited by Konstantinos pap Sunday, March 25, 2018 5:38 PM
    • Marked as answer by Ax1aL Monday, March 26, 2018 5:14 PM
    Sunday, March 25, 2018 5:31 PM

All replies

  • Hi Ax1al,

    First of all i would like to point out that i don't see the reason on doing this. That is the reason inheritance is for. After that i would tell you that both all your classes are private. You can't acces a private member from an instance. It has to be public. By setting them public you will be able to access them. But that will generate another issue. It will throw you an error saying Object reference is not set to an instance of an object. To correct that as well you will have to set the instances of material and Basics that you created inside the Circle class. Here is how your code should look like:

    public class Circle { public class Material { public string type { get; set; } public float smoothness { get; set; } } public class Basics { public int radius { get; set; } public float diameter { get; set; } } public Material mat= new Material(); public Basics basic = new Basics(); }

    Now you can access all the data you want. You could also set the instances in a Cirle constructor like so:

        public class Circle
        {
            public Material mat;
            public Basics basic;
            public Circle() 
            {
                 mat = new Material();
                 basic = new Basics();
            }
    // you could also pass data in there to set them
            public Cirlce(string type, float smoothness, ect)
            {
                mat = new Material();
                mat.type = type;
                mat.smoothness = smoothness;
                basic = new Basic();
                //etc..
            }
    
            public class Material
            {
                public string type { get; set; }
                public float smoothness { get; set; }
    
            }
            public class Basics
            {
                public int radius { get; set; }
                public float diameter { get; set; }
            }
    
        }

    I'd like to point out that there is no reason on doing this since inheritance is the easiest and best way to achieve that. Also in order to access it without a variable all the members inside the class will have to be static. So if you try to access it without creating an instance you would do it like so: Circle.Material.type but the type member has to be static in order to achieve that.

    Hope this helps you.

    Best Regards,

    Konstantinos Pap



    • Edited by Konstantinos pap Sunday, March 25, 2018 5:38 PM
    • Marked as answer by Ax1aL Monday, March 26, 2018 5:14 PM
    Sunday, March 25, 2018 5:31 PM
  • Hello Ax1al,

    >>Circle.Basics/Material is less accessible than fieldCircle.basic/mat

    It doesn't make sense that define public fields in private class, you need to make the class public.

    Nested Types (C# Programming Guide)

    And keep in mind nested types are inaccessible to external types unless you made them public. When you have already defined nested type as public, you could access it like below.

    class program
        {
            static void Main(string[] args)
            {
                Circle.Material circ = new Circle.Material();
                circ.type = "Wood";
            }
        }
        class Circle
        {
            public class Material
            {
                public string type { get; set; }
                public float smoothness { get; set; }
    
            }
            class Basics
            {
                public int radius { get; set; }
                public float diameter { get; set; }
            }
        }

    Best Regards,

    Neil Hu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, March 26, 2018 6:10 AM
    Moderator
  • There is rarely a benefit in using nested types unless the nested type is an implementation detail that would never be exposed (and even then it is rare). There is also no benefit in creating a type to wrap simple collections of data unless you need to treat them as distinct.

    Think for a second about what would happen if you added a new shape to your program, say Square. Would it have a Material as well? If so then would the attributes be the same? If yes then creating a nested type inside each one would be inefficient for several reasons.

    1) You're creating a duplicate, scoped type that has no real relation to the parent type.

    2) You cannot copy "material" from one object to another because they are different types.

    So Material should be its own type that can be applied to any shape.

    For Basics you're using it to group 2 attributes. There is no benefit in doing this. You gain no additional functionality, you are complicating the code that you will need to write to manage it and you are adding extra memory overhead. Simply store the properties in the base class. Only when the data is truly related and needs to be separated should a separate type be used.

    Looking at the data you're storing for Basics you really don't want to do that. Radius and diameter are related values. You don't want to be able to arbitrarily set both of them. If you did then I could create a circle with a radius of 7 and a diameter of 20 which is not mathematically possible. Instead store the core properties and expose get-only properties for the other information.

    class Circle
    {
       //Do you need the center as well?
    
       public int Radius { get; set; }
    
       public int Diameter
       {
          get { return Math.Max(Radius * 2, 0); }
       }
       //Shorter syntax for VS 2017
       //public int Diameter => Math.Max(Radius * 2, 0);
    
       public Material Material { get; set; }
    }
    
    class Material
    {
       public string Type { get; set; }
       public float Smoothness { get; set; }
    }
    
    //Maybe later...
    class Square
    {
       public int Length { get; set; }
    
       public Material Material { get; set; }
    }
    
    //And if you want to treat shapes the same at some level
    abstract class Shape
    {
       public Material Material { get; set; }
    }
    
    class Circle : Shape
    { /* Material goes away */ }
    


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, March 26, 2018 2:15 PM
    Moderator