-
Sep 5th, 2022, 02:59 PM
#1
[RESOLVED] Why No = Operator for ISomething and ISomething
I have a few classes where I overloaded the = operator for convenience sake. Some of this was done many years ago, before I recognized the great value of putting an interface on...pretty much everything. Therefore, when I went back and added interfaces to some of these classes, I had to change the implementations of the Operator = (and <>, of course, since you can't have one without the other).
These methods all take two operands, which will be the left and right operand. For class C, which implements IC, if I want to use IC everywhere, I end up creating two sets of these operators:
Operator = (A as C, B as IC)
and
Operator = (A as IC, B as C)
since I don't know in which order they will be passed. However, what will most often happen is that both A and B would make most sense as IC, and that won't work, because I am not allowed to implement:
Operator = (A as IC, B as IC)
even if the body of such an operator would be trivial (it isn't always).
The reason given for not allowing this, if I am understanding the message right, is that for class C, if there is operator overloading, at least one of the operands must be type C. What is the purpose for this? It's somewhat awkward, in my case, though easy enough to get around, since Equals also has to be implemented, and that can be used in place of IC = IC, but what is the reason why that third operator overloading is not allowed?
My usual boring signature: Nothing
-
Sep 5th, 2022, 03:24 PM
#2
Re: Why No = Operator for ISomething and ISomething
Operator overloading is not bound to an interface. There is no relationship whatsoever between interfaces and operators. Operates are linked to classes therefor one of the operands must be of the same type of the class where the operator is being overloaded. (A as IC, B as IC) is exactly the same as (A as String, B as String). It makes no sense because neither has anything to do with the class itself but if you did (A as C, B as String) then the compiler understands that we want to compare our class with a String. Understand?
-
Sep 5th, 2022, 03:35 PM
#3
Re: Why No = Operator for ISomething and ISomething
At first, no, but then I thought about it a bit more.
Overloaded operators are Shared, and no other Shared method requires that an argument be of the type of the class, but all other shared methods DO require that you indicate which method you are calling, usually by indicating the class name as a Type: C.SomeSharedMethod.
In the case of an operator, there is no means to do that, so the only way it could be implemented would be...excessively messy, as it would have to catalog all overloads and their types to figure out which one was most appropriate, and conflicts couldn't be absolutely ruled out. So, they require one of the operands to be the type as a way to indicate which overload of the operator is the correct one to use.
Good enough.
My usual boring signature: Nothing
-
Sep 5th, 2022, 04:36 PM
#4
Re: [RESOLVED] Why No = Operator for ISomething and ISomething
If you think on it further, you'd realize that (A as IC, B as IC) is actually unnecessary. I suspect the reason you asked about this is because you were concerned about situations where you have different classes defining the same interface. However, this is not a concern since each class would have the comparison defined between itself and the interface so it doesn't matter how you mix and match different classes with the same interface.
-
Sep 5th, 2022, 04:47 PM
#5
Re: [RESOLVED] Why No = Operator for ISomething and ISomething
No, that wasn't where I was coming from. What arose was that I had some classes that didn't have interfaces, but which I realized I needed to extract interfaces for. I had already implemented IEquatable (of C), and was using it in some fairly ancient code where I compared listItem(x) = otherListItem(x). When those were both lists of C, that worked fine. Once those became lists of IC, then that line broke.
Solving that is, as you said, quite simple, since listItem(x).Equals(otherListItem(x)) does the job, but that change had to be made, simple though it was.
My usual boring signature: Nothing
-
Sep 5th, 2022, 06:49 PM
#6
Re: [RESOLVED] Why No = Operator for ISomething and ISomething
Originally Posted by Shaggy Hiker
Once those became lists of IC, then that line broke.
All you needed to fix this was to overload the = with (A as C, B as IC). No need to use Equals:-
Code:
Public Interface IC
Property A As Integer
Property B As Integer
End Interface
Public Class NumberCls
Implements IC
Public Property A As Integer Implements IC.A
Public Property B As Integer Implements IC.B
End Class
Public Class C
Public Property X As Integer
Public Property Y As Integer
Public Shared Operator =(ByVal a As C, ByVal b As IC) As Boolean
Return a.X = b.A AndAlso a.Y = b.A
End Operator
Public Shared Operator <>(ByVal a As C, ByVal b As IC) As Boolean
Return Not (a = b)
End Operator
Public Shared Operator =(ByVal a As IC, ByVal b As C) As Boolean
Return a.A = b.X AndAlso a.B = b.Y
End Operator
Public Shared Operator <>(ByVal a As IC, ByVal b As C) As Boolean
Return Not (a = b)
End Operator
End Class
-
Sep 5th, 2022, 08:25 PM
#7
Re: [RESOLVED] Why No = Operator for ISomething and ISomething
Did that, and no, it doesn't work. What you end up with then is ambiguity. If you try to compare two IC, the compiler can't decide which to use, because both work well enough, and neither is quite correct.
My usual boring signature: Nothing
-
Sep 5th, 2022, 09:21 PM
#8
Re: [RESOLVED] Why No = Operator for ISomething and ISomething
I tested that code I posted and it worked. It compares an object with no interface to a completely different object with the interface using the = operator. Isn't that what you're trying to do?
-
Sep 5th, 2022, 09:22 PM
#9
Re: [RESOLVED] Why No = Operator for ISomething and ISomething
Oh wait.....I think I understand what you're saying.....brb testing....
-
Sep 5th, 2022, 09:46 PM
#10
Re: [RESOLVED] Why No = Operator for ISomething and ISomething
Yea, I see what you're saying now. The best practice here is to have the interface inherit from IEquatable which I believe you already did. The compiler has no way of knowing what is going to be behind those interfaces at compile time so it must prevent that code from compiling.
-
Sep 6th, 2022, 09:37 AM
#11
Re: [RESOLVED] Why No = Operator for ISomething and ISomething
Yeah. I was also wanting to be able to compare two objects that both implemented the interface, regardless of what they were. There are plenty of classes where that isn't possible, and plenty where it is (I have examples of both in the project in question). Allowing for IC = IC would be nice, but it isn't possible. Fortunately, it also doesn't matter, because IC.Equals(IC) IS possible, so long as the interface inherits from IEquatable(of IC).
So, what I'm doing is having any interface that needs to have IC.Equals(IC) implement both IEquatable(of Object) and IEquatable(of IC). This is pretty easy to do, especially since the implementation of IEquatable(of Object) can be written such that it is the same for any interface, which means it's just a matter of copy and paste. What that implementation does is checks to see whether the Object can be cast to a type with a more specific Equals (only those of IC, for most of my implementations), and then calls that version of Equals, otherwise it returns False indicating that they are not Equal. This is correct, since anything that can't be compared certainly can't be equal.
My usual boring signature: Nothing
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|