Membership Operators¶
| Operator | Description |
|---|---|
in |
Membership test |
not in |
Negated membership |
Dispatch Priority¶
The in operator always emits a .Contains() call on the right-hand operand:
This single codegen strategy works uniformly because:
- User-defined classes with
__contains__: The__contains__dunder compiles to a C# method namedContains(viaDunderNameMapping). Sox in objemitsobj.Contains(x), which resolves to the user's__contains__implementation. - Sharpy built-in collections (
list,dict,set): These Sharpy.Core types define aContainsmethod that implements the membership test. - .NET types (
HashSet<T>,List<T>, etc.): These already have a.Contains()method fromICollection<T>or similar interfaces. - Strings:
str.Contains()performs a substring test.
Validation¶
The ProtocolValidator checks that the right-hand operand of in/not in supports membership testing. For user-defined types, the class must define __contains__. For .NET types, the validator checks for a Contains method via CLR interface discovery (ICollection<T>, IDictionary<K,V>, etc.).
If the type does not support membership testing, the compiler reports SPY0333 ("Type does not support membership testing (missing __contains__ method)").
__contains__ Protocol¶
| Property | Value |
|---|---|
| Dunder name | __contains__ |
| Protocol kind | Container |
| C# method name | Contains |
| Expected parameters | 2 (self, item) |
| Expected return type | bool |
Examples¶
# User-defined class with __contains__
class Bag:
_items: list[str]
def __init__(self):
self._items = []
def add(self, item: str) -> None:
self._items.append(item)
def __contains__(self, item: str) -> bool:
for stored in self._items:
if stored.lower() == item.lower():
return True
return False
def main():
bag: Bag = Bag()
bag.add("Hello")
print("hello" in bag) # True (case-insensitive via __contains__)
print("missing" not in bag) # True
# Built-in collections
items: list[int] = [1, 2, 3]
if 2 in items: # Calls list.Contains()
print("Found")
# Strings (substring test)
if "ell" in "Hello": # Calls str.Contains()
print("Found substring")
Implementation
- Lowered: x in y emits y.Contains(x). For Sharpy classes, __contains__ compiles to a C# Contains method, so the same .Contains() call dispatches correctly for both Sharpy and .NET types.