none
C# Array Instance creation Issue RRS feed

  • Question

  • I am new to C# and am converting a VB6 application.

    I am having issues creating a the instances of arrays.

    in Vb we created the instance by looping through the object and using the new keyword to create the instance. Then we could access the new object.

    In C# here is what I created to create the instance in a class

    public class cCore : cGblFunc
        {
            private static double kDegree = 0.3515625;
            private static Single Gr = 386;

            private cAxis[] Axis = new cAxis[Global.kAxisArraySize];
            private cAxisType[] AxisType = new cAxisType[Global.kDriveTrainArraySize];
            private cMotor[] Motor = new cMotor[Global.kMotorArraySize];
            private cCambuilder[] CamTable = new cCambuilder[Global.kAxisTypeArraySize];
            private cDriveTrain[] DriveTrain = new cDriveTrain[Global.kAxisTypeArraySize];
            private cGearBox[] Gearbox = new cGearBox[3];// Global.kAxisTypeArraySize

            //Cams for the part

            private static  cCam[] Cam = new cCam[Global.kAxisTypeArraySize];

    I then created a method to set the values

     public void SetLinearDist(Single Value, int M)
            {
                setLinearDist(Value, M);
            }

    But no matter what I do I get the following error

    System.NullReferenceException: 'Object reference not set to an instance of an object.'

    What am I missing?

    Any help is appreciated

    Tuesday, October 2, 2018 2:58 PM

All replies

  • Can you show the code where it is throwing Null Reference Exception ?

    [If a post helps to resolve your issue, please click the "Mark as Answer" of that post or click Answered "Vote as helpful" button of that post. By marking a post as Answered or Helpful, you help others find the answer faster. ]


    Blog | LinkedIn | Stack Overflow | Facebook
    profile for Ehsan Sajjad on Stack Exchange, a network of free, community-driven Q&A sites

    Tuesday, October 2, 2018 3:46 PM
  • Hello tneon1,

    1. In C#, it is not sufficient to just instantiate an array of instances of a class.

    2. After instantiating an array, e.g. :

    cCam[] Cam = new cCam[Global.kAxisTypeArraySize];

    each item in the Cam array will be set to its default value.

    3. In the case of value types, the default values of each type is used, e.g. for int this is 0, for boolean : false, etc.

    4. In the case of reference types, e.g. string, or cCam, the default value is null.

    5. Hence in the case of the Cam array, each array item must be individually instantiated, e.g. :

    for (int i = 0; i < Global.kAxisTypeArraySize; i++)
    {
      Cam[i] = new cCam();
    }

    and then each Cam array item can be accessed and have its values set.

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    Tuesday, October 2, 2018 4:00 PM
  • Hello,

    I would guess - your - Global - is null or kAxisTypeArraySize throw an exceprion ot it is null/zero/negative.


    Sincerely, Highly skilled coding monkey.

    Tuesday, October 2, 2018 4:35 PM
  • Just some comments:

    - In C# we don't prefix our classes. We use namespaces instead.

    - Use List<yourType> instead of arrays. Use arrays only, when there is a real need or requirement for it.

    - Look at the builder pattern and composition of objects, seems that this applies here.

    - Make your properties accessible by using explicit getters. List, arrays etc should be in many cases made be immutable here. Add access methods for their elements. Consider using sub-classing them, so that you can use indexers.

    And for the concrete error: post a concise and complete example. Without code, it can be anything. But imho Lim Bio is on the correct track.

    Tuesday, October 2, 2018 4:54 PM
  • Here is a screen shot. i am using nested structure and arrays and believe the error is in the .Dist array which is an array of Singles.

    I can see the CAM Array length , but not the .Dist array size

    Tuesday, October 2, 2018 5:34 PM
  • I have used List<> on single arrays, but not on a nested structure of arrays.

    I assume that I would need to convert all arrays to List

    Thanks

    Tuesday, October 2, 2018 5:37 PM
  • > In C# we don't prefix our classes.

    No, we do! We do what ever coding convention tell as to do.

    This didn't affect using of namespaces.


    Sincerely, Highly skilled coding monkey.

    Tuesday, October 2, 2018 5:45 PM
  • >I assume that I would need to convert all arrays to List

    If it working - left it as is.


    Sincerely, Highly skilled coding monkey.

    Tuesday, October 2, 2018 5:47 PM
  • Hello tneon1,

    1. Since Dist is a member of the Cam class, in your constructor for Cam, you should instantiate Dist.

    2. From your code, it appears that Dist is an array of Singles.

    3. If I am correct so far, your Cam constructor should look something like :

    public class cCam
    {
        public cCam()
        {
          ...
          Dist = new Single[<suitable size>];
          ...
        }
    }

    4. If Dist is left uninstantiated, it will remain as null (the default value).

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/




    Tuesday, October 2, 2018 6:09 PM
  • Were does this get initialized at. 

    I read that the class constructor was same Name:

    Public cCam()

    {

    }

    but when I do this it becomes an infinite loop and the prog crashes

    Thank You

    Tuesday, October 2, 2018 9:06 PM
  • There where you init an array.


    Sincerely, Highly skilled coding monkey.

    Tuesday, October 2, 2018 10:27 PM
  • Just some comments:

    - Use List<yourType> instead of arrays. Use arrays only, when there is a real need or requirement for it.

    I would say no, use lists only if they are necessary. An array in C# is immutable, a list not. Arrays are faster because it's allocated as a block of memory. So if you don't have to change the array (not the array item content, you can change it) I would always use an array instead of a list to get better performance.

    Greetings, Chris



    • Edited by DerChris88 Tuesday, October 2, 2018 11:48 PM
    Tuesday, October 2, 2018 10:43 PM
  • Hello tneon1,

    1. Have a look at Constructors (C# Programming Guide) for some guidance on C# constructors.

    2. Concerning the arrays and array items that you mentioned in earlier posts, note the following basic principles (some points below have been mentioned before) :

    2.1 An array must be instantiated by the new keyword with indication of the length of the array, e.g. :

    cCam[] Cam = new cCam[Global.kAxisTypeArraySize];

    2.2 When the above code is executed, Cam array will initially be an array of NULL values.

    2.2 Each Cam array item must be instantiated to an actual cCam object, e.g. :

    for (int i = 0; i < Global.kAxisTypeArraySize; i++)
    {
      Cam[i] = new cCam();
    }

    3. The cCam class itself must be careful to initialize its own members.

    3.1 Any value type members will be initialized to its default value unless it is specifically set, e.g. :

    class cCam
    {
       ...
       private int i1;
       private int i2 = 100;
       private Single[] MySingles1;
       private Single[] MySingles2 = new Single[100];
    }

    In the above code, i1 is initialized to 0 while i2 is specifically initialized to 100.

    MySingles1 is initialized to null while MySingles2 is initialized directly to an array of 100 Singles each of which is initialized to 0.

    4. Hope this helps.

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    Wednesday, October 3, 2018 5:04 AM
  • So in C# were does the initialization occur one time when the object is created? I thought is was the constructor, but my constructor keeps triggering for some reason?

    Thank You


    Wednesday, October 3, 2018 3:34 PM
  • So the CAM Array was the issue. I can create instances of the array but need to do it in the following manner. I do not understand why I cannot the instance directly in the class constructor. I believe I am still missing something.

    I have attached the section of code.

      public class cCore : cGblFunc
        {
            private static double kDegree = 0.3515625;
            private static Single Gr = 386;

            private cAxis[] Axis = new cAxis[Global.kAxisArraySize];
            private cAxisType[] AxisType = new cAxisType[Global.kDriveTrainArraySize];
            private cMotor[] Motor = new cMotor[Global.kMotorArraySize];
            private cCambuilder[] CamTable = new cCambuilder[Global.kAxisTypeArraySize];
            private cDriveTrain[] DriveTrain = new cDriveTrain[Global.kAxisTypeArraySize];
            private cGearBox[] Gearbox = new cGearBox[3];// Global.kAxisTypeArraySize

            //Cams for the part

            private static cCam[] Cam = new cCam[Global.kAxisTypeArraySize];
            public Single EndFwdDeg;
            public Single StartIn;
            public Single InUpOverlap;
            public Single UpFwdOverlap;
            public Single OutRetOverlap;
            public Single LiftPitchOlap;
            public Single PitchLift6Olap;
            private String mMotionType;

            public Single DegPassedFwd;
            public Boolean Mirrored;
            public Boolean StretchRtn;
            public Single PartWeight;
            public Single ToolingWeight;
            public int DieStation;
            public Single spm = 0;
            public Single mspm;       //Max. Possible spm w/o RMS limit checking
            public Single SPMLimit;
            public Boolean ReverseFlow;
            public int PressArraySize;
            //   Used PressType as a String ("Conventional" or "RockLink")
            public String PressType;
            //Ram Up is derived by looking at the Link Drive Ram Displacement Plot
            public Double RamUp;
            //PressStroke is the max stroke of the press
            public Single PressStroke;
            //PresLink is used for caluclations for a Conventional Press
            public Single PressLink;
            //PressDeg is an array to contain the press displacement point plot as a function of degrees and corrispoinding ram distance for a given point
            private List<Single> PressDeg = new List<Single>(); // Dynamic Array, TAF, 8/21/2018
            //RamDist is an array to contain the press displacement point plot as a function of degrees and corrispoinding ram distance for a given point
            private List<Single> RamDist = new List<Single>();// Dynamic Array, TAF, 8/21/2018

            public Single MaxSPM;
            private Boolean[] LastCam = new Boolean[3];
            private Boolean LastMove;

            private Boolean[] mClampStartedFromHome = new Boolean[Global.kAxisTypeArraySize];
            private Boolean mTruncate;


            
            public cCore()
            {

                spm = 0;
                MaxSPM = 100;
                mTruncate = true;
                if (!initCompleted)
                {
                    Init();
                }

            }// end Init Constructor



            public void Init()
            {
                for (int I = 0; I < Global.kAxisTypeArraySize; I++)
                {
                    if (Cam[I] == null)
                    {
                        Cam[I] = new cCam();
                    }
                    if (CamTable[I] == null)
                    {
                        CamTable[I] = new cCambuilder();
                    }
                    if (DriveTrain[I] == null)
                    {
                        DriveTrain[I] = new cDriveTrain();
                    }


        }

                initCompleted = true;
            }

    Wednesday, October 3, 2018 6:20 PM
  • > I do not understand why I cannot the instance directly in the class constructor.

    Because in C# an array of anything is a different class. When you create an array - you call an array constructor, not a constructor of array elements.

    In your case - when you have an array of complex type you may consider to have a container class - can be based on List<t> - and init it in constructor. This will give you expected behavior.


    Sincerely, Highly skilled coding monkey.

    Wednesday, October 3, 2018 6:27 PM
  • P.S. When you do a conversion from VB - try to keep the names and try to encapsulate data. I have inherited app. 2Gb VB6-like undocumented spaghetti code and can't get it properly working - without keeping the names it would absolutely impossible.


    Sincerely, Highly skilled coding monkey.

    Wednesday, October 3, 2018 6:33 PM
  • Andrey is right, if you create an array like this "var array = new Class[5];" you get an array with the size of 5 times size of Class but the items are null. The constructor of Class is never invoked. You have to create an instance for every item in the array. 

    Maybe a job for a factory:

    public static class ArrayFactory
    {
        public static T[] Create<T>(int size, Func<T> provider)
        {
            var array = new T[size];
            for (int i = 0; i < size; i++)
            {
                array[i] = provider();
            }
            return array;
        }
    }

    Instead of calling the constructor use this:

    var array = ArrayFactory.Create(3, () => new Class());


    Greetings, Chris



    • Edited by DerChris88 Wednesday, October 3, 2018 7:34 PM
    Wednesday, October 3, 2018 7:30 PM
  • First thank you all for your understanding and for the great information

    I had a static array in the default class constructor and based on the document that Lim provided which was very good I read that static items need to go into the static class constructor. I made the arrays non static and moved them into the default class constructor to create the instances. See code below. I like all of the suggestions and am going to give them a try as well.

    This works, but is it best practice?

     public cCore()
            {

                spm = 0;
                MaxSPM = 100;
                mTruncate = true;
                for (int I = 0; I < Global.kAxisTypeArraySize; I++)
                {
                    if (Cam[I] == null)
                    {
                        Cam[I] = new cCam();
                    }
                    if (CamTable[I] == null)
                    {
                        CamTable[I] = new cCambuilder();
                    }
                    if (DriveTrain[I] == null)
                    {
                        DriveTrain[I] = new cDriveTrain();
                    }
                }

            }// end Init Constructor

    I am sure I will have more questions.

    Wednesday, October 3, 2018 8:42 PM

  •  public cCore()
            {

                spm = 0;
                MaxSPM = 100;
                mTruncate = true;
                for (int I = 0; I < Global.kAxisTypeArraySize; I++)
                {
                    if (Cam[I] == null)
                    {
                        Cam[I] = new cCam();
                    }
                    if (CamTable[I] == null)
                    {
                        CamTable[I] = new cCambuilder();
                    }
                    if (DriveTrain[I] == null)
                    {
                        DriveTrain[I] = new cDriveTrain();
                    }
                }

            }

    Why if == null? Or what do you think is better:

    //Part 1

    Class a; if (a == null) a = new Class(); // Or

    //Part 2 Class b = new Class();

    Your code is like part 1. If you already know it's null you can just set it. The if is redundant in this case.

    Imho it's not best practice but it's ok if you like and understand it...

    Greetings, Chris

    Wednesday, October 3, 2018 9:35 PM
  • C# static is an item which shared by all instances of class.

    If you have static changed to non-static - you will have item in each instance.

    Translation from VB is not just conversion of operators... 

     

    Sincerely, Highly skilled coding monkey.

    Wednesday, October 3, 2018 9:38 PM

  • ... need to go into the static class constructor ...

    Static classes cannot have instance constructors. I'm a bit confused about what you are trying to do ...

    Greetings, Chris

    Wednesday, October 3, 2018 9:49 PM

  • ... need to go into the static class constructor ...

    Static classes cannot have instance constructors. I'm a bit confused about what you are trying to do ...

    Greetings, Chris

    Ah OK I think I know now what you mean. But you have to think about what Andrey Belyakov said. This constructor is just called once when the static class is used the first time and after that it's like a singleton.

    Greetings, Chris

    Wednesday, October 3, 2018 10:00 PM
  • Thus "Use arrays only, when there is a real need or requirement for it."..

    But the reason for this is, that imho generics have better type saftey. Cause covariance allows

    object[] array = new string[1];
    array[0] = 1;

    to be compiled, but it will throw an runt-time error. This is not possible using generics.

    Or Don Knuth in short: Make it run, make it right, make it fast.

    So in this sense, using a generic is preferable over arrays.

    Thursday, October 4, 2018 12:43 PM
  • Nope. We don't obey conventions, which hide complexity in object names. 

    What does the c prefix denote? Why isn't it expressed in code instead of convention?

     
    Thursday, October 4, 2018 12:46 PM
  • > Why isn't it expressed in code instead of convention?

    Because there are no new development. There are a conversion from VB6 code,

    When you "properly" name a classes and objects you loose a connection between old VB6 and new C# code.

    And when you need to compare a result you have no reference to the point where to conduct the check. 

    I would be very happy to rename my classes extracted from VB.NET (written in VB6 style) to something more suitable for a task, but even smallest changes cause significant loose of time when something goes wrong. And it all the times going wrong,


    Sincerely, Highly skilled coding monkey.

    Thursday, October 4, 2018 1:16 PM
  • ...

    What does the c prefix denote? ...

     

    It's called hungarian notation (often used in C). "c" means it's a class, not a struct... I would not try to force other people to use my own conventions. There are different conventions from project to project and from company to company. I would also not change it because of the technical documentation. It would be much work to change it there, too. A good programmer should know how to get along with different conventions. But I know, a lot of programmer are stubborn about using different conventions...

    But this is just my opinion...

    And I understand your opinion about array vs lists. It's easier to handle lists and they are less error-prone, that's true.

    Op should choose what to use (array/list, hungarian notation/no notation)...


    Greetings, Chris

    Thursday, October 4, 2018 1:54 PM
  • Thus "Use arrays only, when there is a real need or requirement for it."..

    But the reason for this is, that imho generics have better type saftey. Cause covariance allows

    object[] array = new string[1];
    array[0] = 1;

    to be compiled, but it will throw an runt-time error.  

     

    Any C# programmer, really interested in this language, already knows that the bug you mentioned, is a bug introduced in the C# language, purposely, by the language architects, due to CLR team requirements!

    Consequently, this specific covariance syntax should never be used by any C# language programmer, and, therefore, should never be used as argument to validate or invalidate anything.

    Just don't use such buggy covariance!


    Or Don Knuth in short: Make it run, make it right, make it fast.


    In other words, you are meaning that array(s) should be used.

    P.S.: the lang spec tells how arrays are built, and why they are faster...

    BTW, " c " means count.

    • Edited by ritehere44 Thursday, October 4, 2018 10:23 PM BTW
    Thursday, October 4, 2018 10:21 PM
  • BTW, " c " means count.

    Yes you are right... class is gr
    • Edited by DerChris88 Thursday, October 4, 2018 10:39 PM
    Thursday, October 4, 2018 10:38 PM
  • Real hungarian notation should be:

    private grAxis[] cAxis = new grAxis[Global.lAxisArraySize];

    But I don't care, it's the choice of the op and he/she has to understand it ...

    He/She can use the notation how he/she wants.


    BTW: In this case it looks like op wants to use "c" for classes. This making more sense than using gr (group) for structs and classes. Why? Context! The op calls the class cAxis NOT the array!


    • Edited by DerChris88 Friday, October 5, 2018 12:19 AM BTW
    Thursday, October 4, 2018 10:45 PM