Skip to main content

How to Resolve Error "CS0855: An expression tree may not contain an indexed property" in C#

The Compiler Error CS0855 is a limitation of Expression Trees when interacting with Indexed Properties. The message reads: "An expression tree may not contain an indexed property".

In standard C#, a class can have only one "indexer" (this[int index]). However, technologies like COM Interop (used for Excel/Word automation) or libraries written in VB.NET allow "Named Indexed Properties" (e.g., object.Range["A1"]).

While modern C# syntax allows you to access these properties conveniently in standard code, the Expression Tree API (System.Linq.Expressions) does not have a node type to represent them. Therefore, you cannot use this syntactic sugar inside an expression lambda (like a LINQ query or Expression<Func<...>>).

This guide explains how to bypass this limitation by calling the underlying accessor methods explicitly or moving the logic outside the expression.

Understanding Indexed Properties

  • Standard Indexer: list[0]. Supported in Expression Trees.
  • Indexed Property: excelSheet.Range["A1"]. Technically, Range is a property that takes arguments.

When you compile standard C# code using Range["A1"], the compiler translates it into a method call like get_Range("A1"). However, when building an Expression Tree, the compiler refuses to perform this translation automatically because the tree structure expects a strict Property or Method call, not a hybrid "Property with arguments."

Scenario 1: Accessing COM/Interop Objects

This error is almost exclusively encountered when working with Microsoft Office Interop or other COM libraries inside IQueryable or Expression contexts.

Example of error

You are trying to define an expression that accesses a named indexed property (like Range in Excel or a custom VB.NET collection) using the bracket syntax.

using System;
using System.Linq.Expressions;

// Pseudo-interface representing a COM object (like Excel.Worksheet)
public interface IComWorksheet
{
// A named indexed property (Pseudo-code representation)
// C# sees: string Range[string cell];
string get_Range(string cell);
void set_Range(string cell, string value);
}

public class Program
{
static void Main()
{
// ⛔️ Error CS0855: An expression tree may not contain an indexed property.
// The syntax 'w.Range["A1"]' is syntactic sugar for a method call,
// but Expression Trees do not support this sugar.
Expression<Func<IComWorksheet, string>> expr =
w => w.Range["A1"];
}
}

Solution A: Call the Accessor Method Explicitly

Under the hood, every indexed property is just a method named get_PropertyName and set_PropertyName. You can fix the expression tree by calling the get_ method directly.

using System;
using System.Linq.Expressions;

public class Program
{
static void Main()
{
// ✅ Correct: Call the underlying getter method.
// This creates a valid MethodCallExpression node in the tree.
Expression<Func<IComWorksheet, string>> expr =
w => w.get_Range("A1");
}
}

Solution B: Move the Access Outside (Closure)

If the value of the property is not dependent on the lambda parameter (i.e., you are just trying to read a value from an external object to use in the query), read it into a local variable first.

public class Program
{
static void Main()
{
IComWorksheet sheet = GetSheet();

// 1. Resolve the value in standard C# (where the syntax is valid)
string cellValue = sheet.Range["A1"];

// 2. Use the variable in the expression
// ✅ Correct: The expression tree now simply holds a constant/closure value.
Expression<Func<string>> expr = () => cellValue;
}

static IComWorksheet GetSheet() => null;
}

Conclusion

CS0855 is a conflict between C# syntax sugar and Expression Tree rigidity.

  1. Identify the Property: It usually looks like obj.PropName[index].
  2. Check the Source: Is it a COM object (Excel/Word) or a VB.NET class?
  3. The Fix:
    • Call the Method: Change obj.Prop[i] to obj.get_Prop(i).
    • Extract Variable: Read the value into a local variable before creating the expression.