C
C#2y ago
LukeJ

✅ Invalid cast between interface types

Hello. I'm trying to learn functional programming in C#, so I'm ending up with some unusual code. A part of that is having an array of options marked with their length, like so
IMarked<Arr<Option<Unit>>, CountOfField>
IMarked<Arr<Option<Unit>>, CountOfField>
Since this is so long, I've defined this
public interface FieldUnits : IMarked<Arr<Option<Unit>>, CountOfField> {}
public interface FieldUnits : IMarked<Arr<Option<Unit>>, CountOfField> {}
This inevitably means casting to FieldUnits at some point, and doing so is giving me this error
System.InvalidCastException: 'Unable to cast object of type 'Marked`2[LanguageExt.Arr`1[LanguageExt.Option`1[Unit]],CountOfField]' to type 'FieldUnits'.'
System.InvalidCastException: 'Unable to cast object of type 'Marked`2[LanguageExt.Arr`1[LanguageExt.Option`1[Unit]],CountOfField]' to type 'FieldUnits'.'
I'm not sure why though, since they seem to be the same. I also swear this was working the other day. Any ideas what's wrong here? Here's a sample line that has this problem
var units = (FieldUnits)Enumerable.Repeat(Option<Unit>.None, CountOfField.Count).ToArr().mark(default(CountOfField));
var units = (FieldUnits)Enumerable.Repeat(Option<Unit>.None, CountOfField.Count).ToArr().mark(default(CountOfField));
18 Replies
Aaron
Aaron2y ago
they might seem the same, but they are not FieldUnits is not the same interface anything that implements FieldUnits is just guaranteed to implement the long one
LukeJ
LukeJ2y ago
Right. I figured that meant I could cast them like this. Looking at it I realised I'm not actually casting to an object at all. VS not complaining about it has me a little confused though.
Aaron
Aaron2y ago
the inverse isn't true though not everything that implements the long one is guaranteed to implement FieldUnits
LukeJ
LukeJ2y ago
Up v down casting, right.
Aaron
Aaron2y ago
VS doesn't complain because it's possible that the return value implements it it doesn't know
LukeJ
LukeJ2y ago
It doesn't know it's casting to an interface and not an object?
Aaron
Aaron2y ago
casting to an interface is a valid thing to do
MODiX
MODiX2y ago
Windows10CE#8553
REPL Result: Success
interface A {}
interface B {}
class C : A, B {}

A GetA() => new C();
B casted = (B)GetA();
interface A {}
interface B {}
class C : A, B {}

A GetA() => new C();
B casted = (B)GetA();
Compile: 474.880ms | Execution: 33.290ms | React with ❌ to remove this embed.
Aaron
Aaron2y ago
because C implements both interfaces
Anton
Anton2y ago
you could define aliases with global usings, which only works for .net6+ I think
LukeJ
LukeJ2y ago
Ah, that would be perfect. It's what I was trying to do with this.
Anton
Anton2y ago
you won't be able to export them as symbols tho, they would ve purely compile time things and local to the project they are defined in
LukeJ
LukeJ2y ago
Ah. That's a shame. Fine in this context, but probably shouldn't get into the habit of it. Is there a way I can get this to cast nicely?
Anton
Anton2y ago
the language is not designed to handle this much generic complexity nicely, so you either have to make your design more dynamic, which is preferable by the design of the language, or have to deal with the noise and unmaintainability of repeating those types source generators is also a way
LukeJ
LukeJ2y ago
I think I crossed that bridge when I started using Language.Ext 😅
Anton
Anton2y ago
in some cases
LukeJ
LukeJ2y ago
C# is not happy with me, nor is my use case.
Accord
Accord2y ago
Closed!
Want results from more Discord servers?
Add your server
More Posts