Proposal: Support setter-only indexers of multiple value types, but same indexer type, and fix indexer implicit conversion/overload "bug" #8469
Unanswered
wrighp
asked this question in
Language Ideas
Replies: 1 comment 8 replies
-
I think type unions will solve this case. You can work around it today by making your own union type. public struct Union<T1, T2>
{
public int type;
public T1 o1;
public T2 o2;
public static implicit operator Union<T1, T2>(T1 value) => new() { type = 0, o1 = value };
public static implicit operator Union<T1, T2>(T2 value) => new() { type = 1, o2 = value };
}
public class MixedIndexer
{
private Dictionary<string, string> stringValue = new();
private Dictionary<string, int> intValue = new();
public Union<string, int> this[string key]
{
set
{
switch (value.type)
{
case 0: stringValue[key] = value.o1; break;
case 1: intValue[key] = value.o2; break;
}
}
}
} Or you can use a library like OneOf. |
Beta Was this translation helpful? Give feedback.
8 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Summary
Explanation: Ambiguity
Currently when creating indexer setters on their own, the compiler treats them as ambiguous, even though their method representation would otherwise be non-ambiguous:
This leads to a compilation error of
CS0121 The call is ambiguous between the following methods or properties: 'MixedIndexer.this[string]' and 'MixedIndexer.this[string]'
, even though there is no actual ambiguity here, due to the lack of getter.Below is a synonymous overload that accomplishes the same thing, it is clear that it is not ambiguous:
Explanation: Implicit
Similarly, if you were to try and work around this with a separate type of key you come across a failure for the compiler to recognize implicit conversions to indexers when using more than one indexer:
It is worth noting that implicit conversion into indexers is normally okay if there is a single one, however with multiple it breaks. This could be broken down into a separate issue, but implementation is likely tied together with how the overloads (or lack thereof) work for indexers.
Motivation/User Story/Okay, but why?
I am currently working on a lua-like table class(blackboard design pattern) that takes in various value types , and I would like to support multiple setters with the same indexer key, but different value types (and one common getter). The purpose is so that the table can take in various struct and primitive types for optimization purposes without having to box them as objects and reinterpret them conditionally when the type is already known.
As an alternative I am currently just using a method-based Set(), but not only would I like to use the indexers, LLM's like Copilot also prefer to use indexers in this manner, and even if it isn't currently possible, it feels like it should be logically consistent with normal method overloading techniques to allow this behavior.
Edit: Similarly if you would ever want to add what is essentially an overload to an indexer later in development, you're just out of luck without pulling out of indexers entirely (this is also an issue with properties in general).
Beta Was this translation helpful? Give feedback.
All reactions