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.