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.
- Assignments: Use
implicit operatororexplicit operatorinstead of overloading=. - Indexing: Use
public Type this[int i](Indexers) instead of overloading[]. - Logical: Overload
&,|,true, andfalseto enable&&and||.