C# operator overload members mirroring - c#

Today I've encountered a problem with operators overloading. I have a class
public sealed class StringIdentifier : IIdentifier
{
private readonly string _identifier;
public StringIdentifier(string identifier)
{
_identifier = identifier;
}
public object GetIdentifier()
{
return _identifier
}
public static implicit operator StringIdentifier(string value) => new StringIdentifier(value);
public static implicit operator string(StringIdentifier value) => value._identifier;
public static bool operator ==(StringIdentifier a, string b) => a?._identifier == b;
public static bool operator !=(StringIdentifier a, string b) => a?._identifier != b;
}
The problem is, that checking if (StringIdentifier == string) uses the written bool operator, however, using if (string == StringIdentifier) does 2 implicit conversions (thus creates single garbage object (StringIdentifier)) to meet the format operator ==(StringIdentifier a, string b).
I know this can be solved by writing the same operator overload just switching the members (i.e. public static bool operator ==(string a, StringIdentifier b), however, that just creates more methods (and pretty much duplicates the code) but logically nothing is changed.
My question is, is there a way to do automatic operator members mirroring (StringIdentifier == string would be mirrored as string == StringIdentifier), so that I would not need to write same comparison overload twice (or call switched members comparison in overload)?

Related

Overloading Primitive Operator (C#)

Is there a way I can overload primitives, for example addition with doubles? I want to automatically round the doubles whenever an operation is performed. My current code is this:
class Test{
public static double operator +(double x, double y){
return Math.Round(x + y)
}
}
but there's an unfortunate error that says "One of the parameters of a binary operator must be the containing type".
No, and this would be horrible. Users using your library would suddenly get different behaviors from their double variables!
You can write and use a wrapper object however:
public struct MyDouble
{
public double Value {get; set;}
public MyDouble(double initValue)
{
Value = initValue;
}
public static double operator +(MyDouble x, MyDouble y){
return Math.Round(x.Value + y.Value)
}
}
You can also make it castable to/from a double, among other options. This way users know they are using your object and won't be surprised when their math operations are rounded.
If you want to assign from a simple double, you would need to define an implicit operator, similar to that of Nullable<T> (source):
public static implicit operator MyDouble(double value) {
return new MyDouble(value);
}
You can't overload operators on primitive types. This would cause havoc in your codebase.
What you can do instead, is to create a simple wrapper around the primitive type, let's say RoundedDouble:
public struct RoundedDouble : IEquatable<RoundedDouble>, IComparable<RoundedDouble>
{
public readonly double Value;
public RoundedDouble(double value)
{
Value = Math.Round(value); // Or anything else
}
public static implicit operator RoundedDouble(double value)
{
return new RoundedDouble(value);
}
public static implicit operator double(RoundedDouble wrapper)
{
return wrapper.Value;
}
public int GetHashCode()
{
return Value.GetHashCode();
}
public bool Equals(object other)
{
if (other is RoundedDouble)
return ((RoundedDouble)other).Value == Value;
return false;
}
public string ToString()
{
return Value.ToString();
}
// Add your operators here, and implement the interfaces
}
This is a structure. It has the same value semantics as a double.
Extend it by adding the operators, and by implementing at least IEquatable<RoundedDouble> and IComparable<RoundedDouble>.

Properly implement comparison of two objects with different type but semantically equivalent

I've found a similar question
How to compare two distinctly different objects with similar properties
that may implicitly and/or in part reply to my question.
Suppose I want compare (without a lot of nested conditions) this object:
class ObjectA {
public string PropertyX { get; set; }
public char PropertyY { get; set; }
public long PropertyZ { get; set; }
}
to a System.String. I'm interested only in equality or inequality (not a range of values about identity).
Implementing IEquatable<string> in ObjectA is a proper choice? I don't care of what simply works, I want to identify the proper pattern for such case.
As other information, please consider that ObjectA will often be supplied as sequence of IEnumerable<ObjectA>.
I don't need to know if "string" == or != objectA instance; sorting is not involved.
Edit to clarify (and help)
Sorry but writing a good question is sometime difficult...
Suppose I can't represent ObjectA as string for the purpose of comparison (violating encapsulation is not an option).
In context-1 I've to match it against PropertyY.
In context-2 I've to match it against an algorithm applied to PropertyY/PropertyZ.
#Oliver solution in the end of the question helps me again (and +1 again).
I can simply define a custom interface:
interface IContextConverter {
string ToEquatableStringForContext1();
string ToEquatableStringForContext2();
}
Since I've also an ObjectB with same logic but different properties, both will implement IContextConverter (or maybe I find a better name) avoiding to violate RAP.
I would strongly recommend to not implement IEquatable<string>, cause especially when working with collections, dictionaries, LINQ, etc. you don't really know when one of these methods will be called somewhere deep inside which leads maybe to subtle bugs.
Due to the fact that you like to compare two objects of different types a simple Comparer<T> wouldn't work also.
So either write a TypeConverter which converts your object into the desired type (in your case a string) or add a method to your object like .ToEquatableString() and use their output to compare your object with the other string.
Here is an example on you could get all elements, that match one of a string in another collection:
IEnumerable<String> otherElements = new[] {"abc", "def", "ghi" };
IEnumerable<ObjectA> myObjects = GetObjects();
var matchesFound = otherElements.Join( // Take the first collection.
myObjects, // Take the second collection.
s => s, // Use the elements in the first collection as key (the string).
obj => obj.ToEquatableString(), // Create a string from each object for comparison.
(s, obj) => obj, // From the matching pairs take simply the objects found.
StringComparer.OrdinalIgnoreCase); // Use a special string comparer if desired.
There are many possibilities.
If you feel an ObjectA is a kind of System.String, you could write a user-defined conversion (implicit or explicit) from ObjectA to System.String, or from System.String to ObjectA, or both directions.
You could also overload the == and != operators with a signature like operator ==(ObjectA oa, string s). Beware that there is difference between oa == s and s == oa.
Either of these two possibilities may lead to confusion. It would also be confusing to override the virtual Equals(object), or to introduce an overload Equals(string). Therefore I don't recommend implementing IEquatable<string>.
Why not simply write a method with an unused name, like public bool EqualsString(string s)? Then you will have to call this method explicitly, of course, but that will lead to less confusion. Another idea would be to use a constructor of signature public ObjectA(string s) and then implement "homogeneous" equality of ObjectA and ObjectA.
NOTE: I do not particulary recommend this solution for this particular case, but I have often used this framework to implement Value Equality for structs. Difficult trade-offs are common in our field, and answers that address those, accompanied by appropriate caveats, seem in order.
I take it that you wish to design Value Equality semamtics on your class in the same fashion as the .NET framework does this for the string class. At a minimum, the following is necessary:
public override bool Equals(object obj) {
return (obj is ObjectA) && this == (ObjectA)obj;
}
bool IEquatable<ObjectA>.Equals(ObjectA rhs) {
return this == rhs;
}
public static bool operator != (ObjectA lhs, ObjectA rhs) {
return ! (lhs == rhs);
}
public static bool operator == (ObjectA lhs, ObjectA rhs) {
return (lhs.PropertyX == rhs.PropertyX);
}
public override int GetHashCode() {
return PropertyX.GetHashCode()
}
Expanding to allow Value comparisons beween ObjectA and string:
bool IEquatable<ObjectA>.Equals(string rhs) {
return this == rhs;
}
public static bool operator != (ObjectA lhs, string rhs) {
return ! (lhs == rhs);
}
public static bool operator != (string lhs, ObjectA rhs) {
return ! (lhs == rhs);
}
public static bool operator == (ObjectA lhs, string rhs) {
return (lhs.PropertyX == rhs);
}
public static bool operator == (string lhs, ObjectA rhs) {
return (lhs == rhs.PropertyX);
}

How to achieve operator overloading in java and C#?

I know there is no such thing like Operator Overloading in Java and C#. A task is given to me by my teacher to achieve operator overloading in any of these languages. I don't know the deep concepts of these languages, only basic OOP. So can any one tell is there any other way to achieve this?
There is a thing called operator overloading in C#, check out this code snippet from MSDN:
public struct Complex
{
public int real;
public int imaginary;
public Complex(int real, int imaginary)
{
this.real = real;
this.imaginary = imaginary;
}
// Declare which operator to overload (+), the types
// that can be added (two Complex objects), and the
// return type (Complex):
public static Complex operator +(Complex c1, Complex c2)
{
return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
}
}
Full list of overloadable operators
As des has shown, C# does have operator overloading. Java, on the other hand, does not. The way Java compares that two objects are equal is done through overriding the method equals(Object), which is inherited from the base object java.lang.Object. Here's an example usage:
public class MyClass {
private int value;
#Override
public boolean equals(Object o) {
return o instanceof MyClass && ((MyClass)o).value == this.value;
}
}
Of course this is only a workaround for replicating overloading the == operator. For other operators, such as >= or <= there is nothing. However, you can use OO to sort of recreate it by using a common interface:
interface Overloadable<T> {
public boolean isGreaterThan(T other);
public boolean isLessThan(T other);
}
public class MyClass implements Overloadable<MyClass> {
private int value;
#Override
public boolean equals(Object o) {
return o instanceof MyClass && ((MyClass)o).value == this.value;
}
#Override
public boolean isGreaterThan(MyClass other) {
return this.value > other.value;
}
#Override
public boolean isLessThan(MyClass other) {
return this.value < other.value;
}
}
This is by no means real operator overloading because, well, you're not overloading the operators. It does however provide the ability to compare objects in the same way.

Why code inside Generic functions ignores overloaded == operator

What is the workaround to this problem?
class Program
{
static void Main(string[] args)
{
var a = new Test();
var b = new Test();
var eq = Check(a, b);
}
private static bool Check<T>(T a, T b) where T : class
{
return a == b; //will not call overloaded ==
}
}
public class Test
{
public override bool Equals(object obj)
{
Test other = obj as Test;
if (ReferenceEquals(other, null)) return false;
return true;
}
public static bool operator ==(Test left, Test right)
{
return Equals(left, right);
}
public static bool operator !=(Test left, Test right)
{
return !(left == right);
}
}
The == operator is not used because your generic method exists independently of the types you will use for T. It has no way of knowing that all types used as T will overload the == operator... You can use the Equals method instead:
private static bool Check<T>(T a, T b) where T : class
{
return Equals(a, b);
}
The 'solution' here is to call
private static bool Check<T>(T a, T b) where T : class
{
//return a == b; // will not call overloaded ==
return a.Equals(b); // will cal overloaded Equals
}
It's a known behavior. MSDN says:
When applying the where T : class constraint, it is recommended that
you do not use the == and != operators on the type parameter because
these operators will test for reference identity only, not for value equality. This is the case even if these operators are overloaded in
a type used as an argument.
To check equality you have to implement IEqualityComparer (or directly call one of the Equal methods).
The workaround is to call the virtual Equals method, and override that:
private static bool Check<T>(T a, T b) where T : class
{
return a.Equals(b);
}
The overloaded == operator is resolved at compile time, so it is resolved to the System.Object implementation of the operator. A virtual method call is dispatched at run time, so the override of System.Object.Equals (if any) will get called.
In your code, the virtual Equals call is occurring in the overloaded == method, which is not called; that's why the Equals override is not called.
Another solution, if you have control of the classes being passed to the method, would be to constrain to IEquatable<T>, and implement that in your classes:
private static bool Check<T>(T a, T b) where T : class, IEquatable<T>
{
return a.Equals(b);
}
That will cause the overload to resolve to the Equals(T) method, which will save some type checking at run time.

Implementing operators between nullables and base types - should I?

This may well be well-known and discussed, but to my surprise I discovered today that you can give your own implementation of operators between nullables and their base types.
This means that you can have a struct which can be checked for null, and return true.
Now this would be convenient in my situation - on the advice of another member I have a struct that wraps strings. Being able to directly compare this wrapped string directly to null (rather than use a .IsNull or similar) is to me a lot more natural, and means changing from using strings to these WrappedStrings often require no other changes to the code.
But.. the fact that this feature is (I believe) little known, counter-intuitive to anyone thinking struct (which it is) over string (which it represents), and the fact that it confuses ReSharper (structValue == null warns "expression is always false") makes me think this is perhaps a dirty trick left in the dirty but neat tricks cupboard.
So I'm wondering, would you adopt it? If not, would you forgive me for doing so.. or is it really best not to go down this path?
public struct StringWrapper
{
private readonly string str;
public override string ToString() { return str; }
public static bool operator ==(StringWrapper a, StringWrapper b)
{ return a.str == b.str; }
public static bool operator !=(StringWrapper a, StringWrapper b)
{ return !(a == b); }
public static bool operator ==(StringWrapper a, StringWrapper? b)
{
if (!b.HasValue || b.Value.str == null) return a.str == null;
return a == (StringWrapper)b;
}
public static bool operator !=(StringWrapper a, StringWrapper? b)
{ return !(a == b); }
public static bool operator ==(StringWrapper? a, StringWrapper b)
{ return b == a; }
public static bool operator !=(StringWrapper? a, StringWrapper b)
{ return !(a == b); }
public StringWrapper(string str) { this.str = str; }
}
I strongly believe in code that is self-documenting, and goes with the principle of least astonishment. For example, "getters" shouldn't modify data, etc. I would consider comparing a struct variable to null fairly confusing at first glance, so I would avoid it (no matter how convenient it might seem). This would be especially true if you were expecting many people to use (or at least look at) your code.

Categories

Resources