❔ AllOf<>? Something along the same lines as discriminated unions?
Essentially I am trying to write a generic class that is something like this:
Is there absolutely not way to get this to resolve at compile time? I suspect not, but who knows what kind of crazy ideas people can come up with
My current best idea is this, but id like to avoid having to have the setter, but worst case scenario this will probably do the trick
38 Replies
Just a note, if you wish to have a discriminated union now, why not use the OneOf nuget package?
Indeed, and OneOf basically does it by keeping a slot and storing the values in a generated class like
It definitely provides more, but that's the brunt of usage you're looking for
the implicit conversion is the important bit
The issue with one of is I don't need it to satisfy one of the types, I need it to satisfy all of the types, the
Value
should be assignable to both for it to compileyou can't
You can do this with extension methods
That's what I figured, unfortunate that it can't be done with a property, the example I posted in the image is probably as close I can get then
AntonC#3545
REPL Result: Failure
Exception: CompilationErrorException
Compile: 656.721ms | Execution: 0.000ms | React with ❌ to remove this embed.
I wonder of generating IL directly would support something like this, not that I'll go that route but I wonder if its a language limitation or the some other aspect
No, not with a property
Was hoping that because properties are methods under the hood they could be defined as generic (in the IL)
I don't think so
Just don't use a property for this
What's the big deal
It's not a huge deal it's just inconsistent with my other API, but maybe it should be?
Basically it's a networking library and I can have networked variables like
int
and string
but I wanted a way to replicate references to the network entities themselves, so I planned on having a class that was generic in a way that you could specify the types of classes that were allowed in that property, but using just an interface breaks the serializer because it doesn't know about the network ID that exists on the network entity classdon't fuss about the syntax too much
It will still work if I just make it so the generic must be a subclass of my network entity, just was hoping to be able to use interfaces as well
if anything, making that an assignment will make it more obfuscated
I don't think it's obfuscation to require type safety at compile time
no I meant a different thing, I forgot the word... cryptic?
like in the hard or weird to understand sort of way
you just don't normally expect that from a property
I feel like it's a reasonable sacrifice to allow compile time enforcement of types, but I do think it's probably the case that a method like I posted in the image will suffice
extension method are a good solution for this imo
How so? I don't think that solves it at all?
The extensions you provided above satisfy the usual OneOf use case, not "AllOf" that I'm trying to create here
it resolves the right overload based on the argument
I don't want it to work with types that only implement one of the types, for my case it needs to be assignable to all of the types for it to compile
oohh I'm sorry I didn't read your post carefully
No problem haha
That's why I think it's no more "cryptic" than just a regular generic, perhaps less so
you can do this I think
but you'll have to define a class manually for each use case
for each different combination
Yeah that's what I was hoping to avoid sadly
it should be fine tho, unless you make kinds of these types via reflection
It will work yes but it's pretty stinky for users of the library to have to create a new class for every different kind of variable they want, as if generics don't exist
Even if the only user of the library is me haha
I think I've established that the worst case scenario for me is using the generic method solution in the image
Which isn't too bad
write a source generator
if it matters to you this much
Possibly, what would the generated type names be? How would I trigger it? I don't know if a source generator works well here
it does work well here
the generated type names is your own logic
it's triggered by the compiler/the build pipeline
I mean like what syntax would trigger the source generator? If I write
MyClass<ITestInterface> myVariable
then I can't swap out the variable type since it's already in the sourceI would make it an attribute or a partial struct with an attribute
if it's an attribute, you either make the variable the same type as you wrote in the attribute, or mock it with a base interface
you can't use value types in the latter case, obviously
but defining a struct an putting on an attribute is a good enough experience
That could probably work, hmm
ah yeah, the base interface won't work, sorry
it's the same problem as before
well, defining a partial struct, putting an attribute on to it and have it fill up on its own is good enough
but I don't think it's worth it in the end
it's not that much code you have to write for each type
for each combination I mean
This is if you want a struct
well yeah ig you could autogenerate this
and have syntax like
ah, I think I actually know a better solution
generate the extension methods instead
and have the AllOf be opaque (just wrap a value)
you can find which overloads to generate based on usage
look up linqgen
could be helpful
GitHub
GitHub - cathei/LinqGen: Alloc-free and fast replacement for Linq, ...
Alloc-free and fast replacement for Linq, with code generation - GitHub - cathei/LinqGen: Alloc-free and fast replacement for Linq, with code generation
That's not a bad idea, I worry about how it will work with types outside the current assembly however
it won't
the new extensions will have to be defined in the assembly you use it in
you might as well make them internal
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.