Hmm… this is only an issue if your method already has side effects, which in itself is a code smell. While I agree that, like many features of c#, these operators can be misused, they also have lots of merit when used properly.
Could you give an example for a situation where you might run into this code?
Casting one class instance into an unrelated class is strange enough, but I would consider modifying the state of objects that were passed as parameters as a code smell.
It sounds a bit like “Don’t wear a red shirt! Because when I stand in this bull fight arena and wave around with it…” 😉
Check out the StackExchange.Redis client library. It’s chock full of every type of implicit and explicit operator to handle converting datatypes into String which is all Redis stores and back again. First time I dug into it I was like what the heck is this 😛
https://github.com/StackExchange/StackExchange.Redis/blob/main/src/StackExchange.Redis/RedisValue.cs
You’d be surprised.
One of the only gotchas I know in Unity revolves around they tried to “help” by overloading operator==
to consider their objects equal to null if they’ve been disposed. But as people discovered, since that isn’t polymorphic, relying on that shortcut can cause you to get ObjectDisposedExceptions later.
Agreed. You may have a cookie.
Thanks for this. That bug would have definitely caught me off guard. Was not expecting that. I don’t ever use implicit/explicit operators like that so I wasn’t too familiar with their behaviour
The only time I use it is on generic response objects. Being able to pass a response «directly» into the mapping logic when everything works, but being able to inspect the container it lives in when needed, just makes everything so clean.
Super dangerous though..
I’ve used casting overloads quite a few times when I have sort of a “special” form of another existing type and want to use preexisting code. So stuff like
FixPoint => Decimal
VectorPolar => VectorCartesian
MyDateTime => DateTime
ScriptVariable => int/string/decimal/and more.
I know what the article wants to say but… The example is terrible
Constructor overloads or factory methods would have the exact same issue though because they are the same thing with slightly different syntax. There is just a difference of expactation. It is expected from a cast operator that it performs a deep clone if there is mutable data involved but not with a constructor call.
I don’t remember ever using casting operators for reference types though but I could see them used in command patterns or request/response objects.
I’ve suggested on the NSwag to solve the oneOf
issue using explicit casting because you can then define a class for the complete oneOf
case and explicit or implicit cast for all the valid values of that oneOf
class. This allows you to mix value types and references types without going for object
, and one type can be a member of more than one oneOf
class which you can’t with inheritance.
In one of our projects, we used explicit converisons for converting auto-generated objects from swagger/nswag to our business objects/view models and vice versa. Calling the API with the auto-generated client became quite concise and readable.
Or simply avoid using mutable types.
Reminds me how smart it is to learn the depth of design patterns before the breadth of a language.
C# devs
null reference exceptions