Skip to main content

How to Resolve Error "CS1037: Overloadable operator expected" in C#

The Compiler Error CS1037 is a syntax error regarding Operator Overloading. The message reads: "Overloadable operator expected".

C# restricts which symbols can be redefined for custom types. While you can customize the behavior of math (+, -) and comparison (==, >) operators, you cannot overload operators that are fundamental to the language's memory or flow control mechanics, such as assignment (=), access (.), or casting (()).

This error occurs when you attempt to write an operator method, but the symbol you provide is not on the list of allowed overloadable operators.

Understanding Overloadable Operators

You can overload these:

  • Unary: +, -, !, ~, ++, --, true, false
  • Binary: +, -, *, /, %, &, |, ^, <<, >>
  • Comparison: ==, !=, <, >, <=, >=

You cannot overload these (triggers CS1037):

  • Assignment: =, +=, -=, etc. (Compound assignment is handled automatically if you overload the binary operator).
  • Access: ., ?.
  • Indexing: [] (Use Indexers instead).
  • Logical: &&, || (Compiler generates these using &, |, true, false).
  • Other: new, as, is, sizeof, typeof.

Scenario 1: Attempting to Overload Assignment (=)

In C++, it is common to overload the assignment operator = to handle deep copying. In C#, assignment is strictly a memory operation (copying the value or reference). You cannot change what = does.

Example of error

public class Box
{
public int Value;

// ⛔️ Error CS1037: Overloadable operator expected.
// '=' is not an overloadable operator symbol in C#.
public static Box operator =(Box a, int b)
{
a.Value = b;
return a;
}
}

Solution: Use Conversion Operators

If you want to assign an int to a Box variable (e.g., Box b = 10;), use an Implicit Conversion Operator.

public class Box
{
public int Value;

// ✅ Correct: Allows 'Box b = 10;'
public static implicit operator Box(int b)
{
return new Box { Value = b };
}
}

Scenario 2: Attempting to Overload Indexing ([])

Developers often try to overload [] to allow array-like access to their class, using the standard operator syntax. However, C# uses a specific feature called Indexers for this.

Example of error

public class DataList
{
private string[] _data = new string[10];

// ⛔️ Error CS1037: Overloadable operator expected.
// You cannot use 'operator []'.
public static string operator [](DataList list, int index)
{
return list._data[index];
}
}

Solution: Use Indexer Syntax

Define an Indexer using the this keyword.

public class DataList
{
private string[] _data = new string[10];

// ✅ Correct: The C# syntax for array-like access.
public string this[int index]
{
get { return _data[index]; }
set { _data[index] = value; }
}
}

Scenario 3: Attempting to Overload Logical Operators (&&, ||)

C# supports short-circuiting logic (&& and ||). You cannot define these behaviors directly because they involve control flow (skipping evaluation).

Example of error

public class SmartBool
{
// ⛔️ Error CS1037: Overloadable operator expected.
// '&&' cannot be overloaded directly.
public static SmartBool operator &&(SmartBool a, SmartBool b)
{
// ...
}
}

Solution: Overload Bitwise and Boolean Operators

To enable &&, you must overload the bitwise AND (&) and the boolean operators (true, false). The compiler will then automatically synthesize the && logic.

public class SmartBool
{
public bool Value;

// 1. Overload '&'
public static SmartBool operator &(SmartBool a, SmartBool b)
{
return new SmartBool { Value = a.Value & b.Value };
}

// 2. Overload 'true' and 'false'
public static bool operator true(SmartBool x) => x.Value;
public static bool operator false(SmartBool x) => !x.Value;
}

// Now you can use: if (obj1 && obj2) ...

Conclusion

CS1037 is the compiler enforcing the boundaries of customization.

  1. Assignments: Use implicit operator or explicit operator instead of overloading =.
  2. Indexing: Use public Type this[int i] (Indexers) instead of overloading [].
  3. Logical: Overload &, |, true, and false to enable && and ||.