Click here to Skip to main content
15,860,861 members
Articles / Programming Languages / C++/CLI
Article

Using managed arrays

Rate me:
Please Sign up or sign in to vote.
4.78/5 (26 votes)
24 Jun 20023 min read 229.4K   971   31   20
Declaring and using managed .NET arrays with MC++

Introduction

Managed C++ allows you to declare and use Managed .NET arrays which means you don't have to do memory allocation of your own and garbage collection will take care of memory de-allocation. Managed .NET arrays are basically objects of the System::Array class and thus you have the additional benefit that you can call methods of the System::Array class on your Managed .NET arrays. Both single and multi-dimensional arrays are supported though the syntax is slightly different from that used with old-style unmanaged arrays.

Single dimensional arrays

Arrays of a Reference  type

MC++
String* StrArray[] = new String* [5];
for(int i=0;i<5;i++) 
    StrArray[i] = i.ToString();
for(int i=0;i<5;i++) 
    Console::Write("{0} ",StrArray[i]);

Here the syntax is not much too different from that in unmanaged code, except that the array we create will be managed and thus garbage collected. Just as in unmanaged arrays, the array index is zero based.

Arrays of a Value type

MC++
int NumArray __gc[] = new int __gc[5];
for(int i=0;i<5;i++)
    NumArray[i]=i;
for(int i=0;i<5;i++)
    Console::Write("{0} ",__box(NumArray[i]));

For value types you have to explicitly use the __gc keyword when declaring arrays. If we do not use the __gc keyword the new operator will create an unmanaged array. But of course, the array members are still native value types and thus we need to box them into managed types using the __box keyword when passing them to Console::Write.

Multi-dimensional arrays

MC++
String* MultiString[,] = new String*[2,3];
for(int i=0;i<2;i++)
    for(int j=0;j<3;j++)
        MultiString[i,j] = String::Format("{0} * {1} = {2};",
            __box(i),__box(j),__box(i*j));
for(int i=0;i<2;i++)
{
    for(int j=0;j<3;j++)
        Console::Write("{0} ",MultiString[i,j]); 
    Console::WriteLine();
} 

Whoa! What's that, eh? Looks really weird, huh? I thought so too when I first came across the Managed C++ style of declaring Managed .NET arrays. You now have just one pair of brackets and each of the dimensional indexes are separated by commas. Unlike in unmanaged arrays, a 2-dimensional array is NOT an array of arrays. It is simply a 2-dimensional array.

Jagged arrays

Jagged arrays are multi-dimensional arrays that are non-rectangular. For example, you can have a 2-dimensional array where each of the single dimensional sub-arrays are of a different dimension. Unfortunately you cannot have jagged arrays in Managed C++ because there is currently no support for jagged arrays. What might piss you off even more is the fact that C# supports jagged arrays. But then you can always simulate jagged arrays which is what I did. It's not the same thing really, and I do hope they add jagged array support in the next release of VC++ .NET.

Jagged array Simulation

MC++
Array* Multi[] = new Array*[2];
Multi[0] = new String*[4];
Multi[1] = new String*[2];
for(int i=0;i<2;i++)
    for(int j=0; j<Multi[i]->Length;j++)
        Multi[i]->SetValue(String::Format("{0} * {1} = {2};",
            __box(i),__box(j),__box(i*j)),j);
for(int i=0;i<2;i++)
{
    for(int j=0; j<Multi[i]->Length;j++)
        Console::Write("{0} ",Multi[i]->GetValue(j));
    Console::WriteLine();
} 

What I did was to create an array of System::Array objects and then I initialized each of those System::Array objects to an array of String objects. And we access an object as Multi[i]->GetValue(j) where i and j are the dimensional indexes. I know that some of you are groaning right now, but I couldn't find any alternative solution. I have posted this in the VC++ .NET newsgroups too but haven't got any responses.

Arrays as Function arguments

Array of Managed types

MC++
static void MakeArrayUpper(String* TwoDArray[,])
{
    for(int i=0;i <= TwoDArray->GetUpperBound(0); i++)
        for(int j=0;j <= TwoDArray->GetUpperBound(1); j++)
            TwoDArray[i,j]=TwoDArray[i,j]->ToUpper(); 
}

Well that was rather straightforward, wasn't it? I have used

GetUpperBound
which is a member method of the System::Array class on our array. As mentioned earlier and as I will explain later down below, we can use any System::Array method on our arrays.

Array of value types

MC++
static void DoubleIntArray(int int_array __gc[])
{
    for(int i=0; i< int_array->Length; i++)
        int_array[i] *= 2;
}

Well this is just about similar to the previous version except that we have used the __gc keyword here. One very interesting issue here is that arrays of value types are passed by reference. This might seem odd at first glance, but remember that the array itself is a System::Array object and is thus a managed type which means it's always passed by reference.

Returning arrays from functions

MC++
static String* CreatePopulateDummyArray() [,]
{
    String* Small[,] = new String* [2,2];
    Small[0,0] = "Colin Davies";
    Small[0,1] = "James T Johnson";
    Small[1,0] = "Kannan Kalyanaraman";
    Small[1,1] = "Roger Wright";
    return Small;
}

LOL. I can imagine the incredulous look on some of your faces. For whatever reasons they might have had, Microsoft have decided to make it this way and so be it. After all this is C++ and it's not ever expected to make things easier for anyone. Well, so whenever we want to return a managed array, we suffix our function name with our array's dimensional order. Well, when you consider that in unmanaged C++ there was no way to actually return an array except by returning a pointer to it's first element, I must say that this is a great improvement. Now you can actually do something like this.

MC++
String* Small[,] = Test::CreatePopulateDummyArray();

Calling System::Array methods

MC++
Array::Sort(nArray);
for(int i=0;i<3;i++)
    Console::Write("{0} ",__box(nArray[i]));
Console::WriteLine();
Array::Reverse(nArray);
for(int i=0;i<3;i++)
    Console::Write("{0} ",__box(nArray[i]));
Console::WriteLine();

I have used Array::Sort and Array::Reverse on my arrays. Now isn't that handy?

Full Source Listing

MC++
#include "stdafx.h"

#using <mscorlib.dll>
#include <tchar.h>

using namespace System;

__gc class Test
{
public:
    static void MakeArrayUpper(String* TwoDArray[,])
    {
        for(int i=0;i <= TwoDArray->GetUpperBound(0); i++)
            for(int j=0;j <= TwoDArray->GetUpperBound(1); j++)
                TwoDArray[i,j]=TwoDArray[i,j]->ToUpper();        
    }
    static String* CreatePopulateDummyArray() [,]
    {
        String* Small[,] = new String* [2,2];
        Small[0,0] = "Colin Davies";
        Small[0,1] = "James T Johnson";
        Small[1,0] = "Kannan Kalyanaraman";
        Small[1,1] = "Roger Wright";
        return Small;
    }
    static void DoubleIntArray(int int_array __gc[])
    {
        for(int i=0; i< int_array->Length; i++)
            int_array[i] *= 2;
    }
};

int _tmain(void)
{    
    //Single dimensional arrays - reference types
    String* StrArray[] = new String* [5];
    for(int i=0;i<5;i++)    
        StrArray[i] = i.ToString();
    for(int i=0;i<5;i++)    
        Console::Write("{0}  ",StrArray[i]);
    Console::WriteLine();

    //Single dimensional arrays - value types
    int NumArray __gc[] = new int __gc[5];
    for(int i=0;i<5;i++)
        NumArray[i]=i;
    for(int i=0;i<5;i++)
        Console::Write("{0}  ",__box(NumArray[i]));
    Console::WriteLine();

    //Multi dimensional arrays
    String* MultiString[,] = new String*[2,3];
    for(int i=0;i<2;i++)
        for(int j=0;j<3;j++)
            MultiString[i,j] = String::Format("{0} * {1} = {2};",
                __box(i),__box(j),__box(i*j));
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<3;j++)
            Console::Write("{0}  ",MultiString[i,j]);    
        Console::WriteLine();
    }    

    //Simulating jagged arrays
    Array* Multi[] = new Array*[2];
    Multi[0] = new String*[4];
    Multi[1] = new String*[2];
    for(int i=0;i<2;i++)
        for(int j=0; j<Multi[i]->Length;j++)
            Multi[i]->SetValue(String::Format("{0} * {1} = {2};",
                __box(i),__box(j),__box(i*j)),j);
    for(int i=0;i<2;i++)
    {
        for(int j=0; j<Multi[i]->Length;j++)
            Console::Write("{0}  ",Multi[i]->GetValue(j));
        Console::WriteLine();
    }        

    //Passing arrays as arguments to functions and 
    //returning arrays back from the function
    String* Small[,] = Test::CreatePopulateDummyArray();

    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            Console::Write("{0}  ",Small[i,j]);
    Console::WriteLine();
    Test::MakeArrayUpper(Small);
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            Console::Write("{0}  ",Small[i,j]);
    Console::WriteLine();

    //Passing an int array by reference
    int nArray __gc[] = new int __gc[3];
    nArray[0] = 5;
    nArray[1] = 7;
    nArray[2] = 2;
    for(int i=0;i<3;i++)
        Console::Write("{0}  ",__box(nArray[i]));
    Console::WriteLine();
    Test::DoubleIntArray(nArray);
    for(int i=0;i<3;i++)
        Console::Write("{0}  ",__box(nArray[i]));
    Console::WriteLine();

    //Calling Array member methods
    Array::Sort(nArray);
    for(int i=0;i<3;i++)
        Console::Write("{0}  ",__box(nArray[i]));
    Console::WriteLine();
    Array::Reverse(nArray);
    for(int i=0;i<3;i++)
        Console::Write("{0}  ",__box(nArray[i]));
    Console::WriteLine();
    
    return 0;
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
Nish Nishant is a technology enthusiast from Columbus, Ohio. He has over 20 years of software industry experience in various roles including Chief Technology Officer, Senior Solution Architect, Lead Software Architect, Principal Software Engineer, and Engineering/Architecture Team Leader. Nish is a 14-time recipient of the Microsoft Visual C++ MVP Award.

Nish authored C++/CLI in Action for Manning Publications in 2005, and co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his WordPress blog. Nish is experienced in technology leadership, solution architecture, software architecture, cloud development (AWS and Azure), REST services, software engineering best practices, CI/CD, mentoring, and directing all stages of software development.

Nish's Technology Blog : voidnish.wordpress.com

Comments and Discussions

 
QuestionManaged arrays as private variables of a class Pin
Jonathan LaRue15-Jul-07 18:57
Jonathan LaRue15-Jul-07 18:57 
AnswerRe: Managed arrays as private variables of a class Pin
Jonathan LaRue15-Jul-07 19:05
Jonathan LaRue15-Jul-07 19:05 
Questionhow to set the default value like this 1,2,33,455,77,88 Pin
beelzebub3-Jul-06 15:20
beelzebub3-Jul-06 15:20 
Generalreturning a managed array Pin
htuba7-Jul-05 8:16
htuba7-Jul-05 8:16 
GeneralString Arrays By Reference Pin
jcarlaft7-Apr-05 5:21
jcarlaft7-Apr-05 5:21 
Generalpassing unmanaged arrays to managed arrays. Pin
PDHB24-Apr-04 16:18
PDHB24-Apr-04 16:18 
GeneralRe: passing unmanaged arrays to managed arrays. Pin
patnsnaudy24-May-04 10:33
patnsnaudy24-May-04 10:33 
Generalerror C3845 Pin
shiggity s5-Apr-04 21:02
shiggity s5-Apr-04 21:02 
Generaltemplates and arrays Pin
KevinHall16-Oct-03 13:48
KevinHall16-Oct-03 13:48 
Generalarrays, c++ .net Pin
RBlyth9-Oct-03 3:02
RBlyth9-Oct-03 3:02 
Generalany function similar to CArray::GetData Pin
Uma Mahes22-Jun-03 21:26
Uma Mahes22-Jun-03 21:26 
GeneralRe: any function similar to CArray::GetData Pin
Nish Nishant24-Jul-03 5:53
sitebuilderNish Nishant24-Jul-03 5:53 
GeneralJune 25 update Pin
Nish Nishant26-Jun-02 15:05
sitebuilderNish Nishant26-Jun-02 15:05 
GeneralDynamic Arrays (C#) Pin
Caleb Groom14-Oct-01 19:02
Caleb Groom14-Oct-01 19:02 
GeneralRe: Dynamic Arrays (C#) Pin
Nish Nishant14-Oct-01 20:11
sitebuilderNish Nishant14-Oct-01 20:11 
GeneralRe: Dynamic Arrays (C#) Pin
Caleb Groom14-Oct-01 20:45
Caleb Groom14-Oct-01 20:45 
Thats what I was afraid of. Have you ever used the STL? Its amazing when it comes to dealing with data structures. I see this as a huge drawback to the .NET Framework. Cry | :((

__________________________
do {
cout << "I will never use = when I mean == " << endl;
} while (i = 1)
GeneralRe: Dynamic Arrays (C#) Pin
Jon Shute14-Oct-01 22:00
Jon Shute14-Oct-01 22:00 
GeneralRe: Dynamic Arrays (C#) Pin
Nish Nishant14-Oct-01 22:56
sitebuilderNish Nishant14-Oct-01 22:56 
GeneralRe: Dynamic Arrays (C#) Pin
Caleb Groom15-Oct-01 4:50
Caleb Groom15-Oct-01 4:50 
GeneralRe: Dynamic Arrays (C#) Pin
19-Feb-02 23:15
suss19-Feb-02 23:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.