Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Provide a new kind of array which is value type #729

Closed
ygc369 opened this issue Jul 9, 2017 · 4 comments
Closed

Proposal: Provide a new kind of array which is value type #729

ygc369 opened this issue Jul 9, 2017 · 4 comments

Comments

@ygc369
Copy link

ygc369 commented Jul 9, 2017

I know there is already a similar issue(#713), but that issue seems to focus on params array or stackalloc array. In this issue, I want to discuss more about it.

  1. Value type array should be a new struct type, different from the current array class, although they might share some syntax, for example [].
  2. Since it is struct, value type array is copied by value, not by ref.
  3. Value type array can be used anywhere, just like normal struct, not only used as local variables, but also used as class/struct fields.
  4. Value type array can be used as params array.
  5. Value type array is mainly used for performance purpose. If small temp arrays could be value type, then heap allocation would be avoided, thus reducing GC pressure. If small arrays are class/struct fields and can not be null, then embedding them in the class/struct itself would reduce heap allocations too.

Here are some examples:

/* 1. used as local variables: allocated on stack, the length need not to be determined at compile time. 
the value type array itself is value type, but its element could be either ref type or value type. */
static void foo(int n)
{
    object[n] valueTypeArray;  // I use Type[n] to represent value type array here
    int i;
    for(i=0;i<n;i++)
    {
        valueTypeArray[i]=new object();
    }
    valueTypeArray[n]=new object(); //Throw IndexOutOfRangeException here! Value type array should also have boundary check (compile-time check), so it is safe.
    ......
}

/* 2. used as params array: allocated on stack. The length need not to be determined at compile time, but need to have a variabe name to be used in the function. The length type is always int. */
static void foo(bool t, params int[n] a) //value type params, different from "params int[] a", which is ref type. 
{
/* Here "n" is an int variable, represent the length of "a", should be treated as another parameter of "foo". 
Value type array might not have Length property (depending on its implementation), so we need "n".
Of course, using other name instead of "n" is OK too. */
    int[n] b=a; //copy by value, length must match.
    int[] c=a; //compile error! Type mismatches, c is ref type, but a is value type.
    ......
}

/* 3. used as normal function parameters (not params array): allocated on stack, and copied by value */
static void foo(bool[2] a, int[m] b)
{
/* the length of a is determined at compile time, while the length of b is determined at run time (depending on the parameter provided by the caller). */
    ......
}

/* 4. used as class/struct fields: allocated on stack or heap, determined by its container. The length must be determined at compile time. */
class A
{
    long a;
    int[10] b;
    object[20] c;
}
struct B
{
    object[2] a;
    int b;
    byte[100] c;
}

/* 5. Value type array could also be used by ref: just like ref struct */
static void foo(ref int[m] a) //a is passed by ref
{
    if(m>1)
    {
        a[0]++;
        a[m-1]--;
    }
}
/* If value type array support initialization and range syntax, we could do more interesting things */
static void main(....)
{
    int[100] a={1,2,5,10}; //initialization: a[0]=1,a[1]=2,a[2]=5,a[3]=10, all other elements are zero.
    foo(ref a[3..10]); //after foo, a[3]=11,a[10]=-1
}
@HaloFour
Copy link
Contributor

HaloFour commented Jul 9, 2017

Same problems. It's not possible to pass something of an arbitrary size on the stack. Both the caller and the callee need to agree on the size of stack memory at compile time. That renders most use cases pointless, particularly params.

@ygc369
Copy link
Author

ygc369 commented Jul 10, 2017

@HaloFour
Thank you for comment. I understand your meaning, maybe most use cases are pointless.
But there is still a use case worth consideration----case 4: used as class/struct fields. In this case, the length must be determined at compile time.
Except case 4, All other cases can be covered by Span<T>.(There is already a proposal about params Span<T>.)

@HaloFour
Copy link
Contributor

@ygc369

I believe that use case falls under #78 which seeks to improve support for fixed buffers. Span<T> might play into making that accessible to safe code.

@ygc369 ygc369 closed this as completed Jul 10, 2017
@jnm2
Copy link
Contributor

jnm2 commented Oct 4, 2018

Fyi, work has started on stack-allocated objects. dotnet/coreclr#20251

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants