How to Resolve Error "CS0838: An expression tree may not contain a multidimensional array initializer" in C#
The Compiler Error CS0838 is a limitation of the Expression Tree system in C#. The message reads: "An expression tree may not contain a multidimensional array initializer".
In C#, Expression Trees (Expression<Func<...>>) act as data structures representing code logic. While standard Delegates (Func) support almost all C# syntax, Expression Trees have specific limitations. One of these limitations is the initialization of Multi-dimensional Arrays (e.g., new int[2, 2] { {1, 2}, {3, 4} }). The compiler simply does not have the logic to translate this specific initialization syntax into an Expression Tree node.
This guide explains how to work around this limitation using jagged arrays or external variables.
Understanding the Limitation
C# supports two main types of arrays:
- Jagged Arrays (
int[][]): An array of arrays. Supported in Expression Trees. - Multi-dimensional (Rectangular) Arrays (
int[,]): A single block of memory with multiple dimensions. Not fully supported in Expression Trees.
Specifically, you can declare a rectangular array inside an expression, but you cannot use the initializer list ({ ... }) to populate it inline.
- Valid:
() => new int[2, 2](Creates empty array). - Invalid:
() => new int[2, 2] { { 1, 1 }, { 2, 2 } }(CS0838).
Scenario 1: Initializing Rectangular Arrays inside Expressions
This error occurs when you define an Expression variable and try to return a populated 2D array literal.
Example of error
using System;
using System.Linq.Expressions;
public class Program
{
static void Main()
{
// ⛔️ Error CS0838: An expression tree may not contain a multidimensional array initializer.
// The syntax '{ {1, 1}, ... }' cannot be converted to an expression tree node.
Expression<Func<int[,]>> expr = () => new int[2, 2] { { 1, 1 }, { 2, 2 } };
}
}
Solution: Initialize Outside the Expression
If the data is constant or known beforehand, create the array outside the expression and simply reference the variable. The Expression Tree handles variable access (Closure) perfectly fine; it just chokes on the creation syntax.
using System;
using System.Linq.Expressions;
public class Program
{
static void Main()
{
// 1. Create the array using standard C# code
int[,] data = new int[2, 2] { { 1, 1 }, { 2, 2 } };
// 2. Reference the variable inside the expression
// ✅ Correct: The expression tree now represents "return constant/variable", which is valid.
Expression<Func<int[,]>> expr = () => data;
// Output verification
int[,] result = expr.Compile().Invoke();
Console.WriteLine(result[0, 0]); // Output: 1
}
}
Scenario 2: Using Jagged Arrays Instead
If you must define the structure inline (for example, if the structure depends on parameters passed into the expression), you should switch from a Rectangular Array ([,]) to a Jagged Array ([][]).
Jagged arrays are essentially standard 1D arrays where each element happens to be another array. Since 1D array initialization is supported in Expression Trees, this works recursively.
Example of error
Trying to force a grid structure using [,].
public class MatrixBuilder
{
public void Build()
{
// ⛔️ Error CS0838
Expression<Func<int[,]>> matrix = () => new int[2, 2] { { 1, 2 }, { 3, 4 } };
}
}
Solution: Use Jagged Arrays
Change the type definition to int[][] and update the initialization syntax.
using System;
using System.Linq.Expressions;
public class MatrixBuilder
{
public void Build()
{
// ✅ Correct: Jagged arrays (array of arrays) are fully supported.
Expression<Func<int[][]>> matrix = () => new int[][]
{
new int[] { 1, 2 },
new int[] { 3, 4 }
};
var result = matrix.Compile().Invoke();
Console.WriteLine(result[1][0]); // Output: 3
}
}
Difference in Access:
- Rectangular:
arr[row, col] - Jagged:
arr[row][col]
Conclusion
CS0838 is a specific gap in the Expression Tree feature set.
- Check Syntax: Are you using
new Type[x, y] { ... }inside anExpression<T>? - Variable Workaround: If the data is static, create the array outside the lambda and pass it in as a variable.
- Jagged Workaround: If the structure must be defined inline, switch to Jagged Arrays (
Type[][]).