why operator overloading is necessary in c# - c#

class MyNumber
{
public int Number { get; set; }
}
I don't understood why the below code will throw error.
class Program
{
public static void Main()
{
MyNumber firstNumber = new MyNumber();
MyNumber secondNumber = new MyNumber();
firstNumber.Number = 10;
secondNumber.Number = 5;
MyNumber sum = firstNumber + secondNumber;
}
}

Currently there is no + operator defined for MyNumber this means that you get a syntax error when you try to use it, instead you probably want something like this:
class MyNumber
{
public int Number { get; set; }
public static MyNumber operator +(MyNumber c1, MyNumber c2)
{
//sum the .Number components and return them as a new MyNumber
return new MyNumber{ Number = c1.Number + c2.Number };
}
}
What this does is explain what + means in the context of your MyNumber class

Each of these addition operators yields different results based on the type it is used against.
string s = "Foo" + "Bar"; //Resulting in FooBar
int i = 1 + 3; //Resulting in 4
Now for your custom class, how do you expect the operator to function if you dont tell it what to do?

The answer is really simple the compiler does not know how to handle those operation for your custom type.
The example quoted by you is simple, and you want, when I say add + then add the properties with the same name but lets take another example Multiplication* for a basic Complex number class you have already studied and we know multiplication for Complex number class is,
(a + i b) * (c + i d) = ac -bd + i (bc + ad)
do you think so compiler has a magic trick and he knows this is complex number class and multiplication is to be carried like this, Surely it does not know for that you need to tell it this way you have to carry out operation, that's why operator overloading is needed and of course if you don't overload you get exception in Error list stating
Error 1 Operator '+' cannot be applied to operands of type 'ConsoleApplicationTest.Class1' and 'ConsoleApplicationTest.Class1'
So for complex class implementation will be like this,
public class Complex
{
public int real;
public int imaginary;
public Complex(int real, int imaginary)
{
this.real = real;
this.imaginary = imaginary;
}
public static Complex operator *(Complex c1, Complex c2)
{
return new Complex(c1.real * c2.real - c1.imaginary * c2.imaginary, c1.imaginary * c2.real + c1.real * c2.imaginary);
}
}

Related

How I can apply operators "/" and "-" for type list<double> and double?

I wanna do math calculation for every components of a list<double> (TransitTime) in a class, but I don't know how!
the (MaaTransitTime) and (FlTransitTime) aren't list.
public static List<double> TransitTime { get; set; }
public static double MaaTransitTime { set; get; }
public static double FlTransitTime { set; get; }
public static List<double> CalculateSonicPorosity()
{
return (TransitTime-MaaTransitTime)/(FlTransitTime-MaaTransitTime);
}
the compile time error is:
Operator "-" cannot be applied to operands of type List and double.
When querying, you can try Linq:
public static List<double> CalculateSonicPorosity() =>
TransitTime.Select(time => (time - MaaTransitTime) / (FlTransitTime - MaaTransitTime)).ToList();
There is no direct support in c# for what you try to achieve.
If there is a lot of math to do with your lists, you can wrap your list in another object like below:
public class ListWrapper
{
private List<double> list;
public ListWrapper(List<double> list)
{
this.list = list;
}
public static ListWrapper operator -(ListWrapper a, double b)
{
return a.list.Select(x => x - b).ToList();
}
}
Note that this is only a template and there are more methods missing (e.g. you need to implement operators for both combination of parameters and you need an accessor for your list)
That's because a List<double> is of a different type than a double and there is no suitable operator - between the two.
You need to get a double from the List in order to use the operator - with another double.
You will need to overload operators for two new operations: subtraction between a List<double> and a double, and division between two List<double>.
You can create a new class that's either a wrapper for the list like in user1781290's answer or directly inherit from List. Then you can overload operators in that created class.
public class TransitTime : List<double>{
public TransitTime() : base(){
}
public static TransitTime operator - (TransitTime c1, double c2)
{
// Here we implement subtraction as subtracting c2 from every member of c1
TransitTime endTimes = new TransitTime();
for (int i = 0; i < c1.Count; i++){
endTimes.Add(c1[i] - c2);
}
return endTimes;
}
public static TransitTime operator / (TransitTime c1, TransitTime c2)
{
// Here we implement division as dividing every member of c1 by every member of c2
TransitTime endTimes = new TransitTime();
for (int i = 0; i < c1.Count; i++){
endTimes.Add(c1[i] / c2[i]);
}
return endTimes;
}
}
Here's an example:
https://dotnetfiddle.net/BwucL3

How to Create Incompatible Number Subtypes

Note: This question is nearly identical to this one. But this one is about C#, not Java.
In Ada, it is possible to create incompatible equivalent numeric types:
type Integer_1 is range 1 .. 10;
type Integer_2 is range 1 .. 10;
A : Integer_1 := 8;
B : Integer_2 := A; -- illegal!
This prevents accidental logical errors such as adding a temperature to a distance.
Is it possible to do something similar in C#? E.g.
class BookId : int {}
class Book
{
BookId Id;
}
class PageId : int {}
class Page
{
PageId Id;
}
class Word
{
BookId BookId;
PageId PageId;
string text;
}
var book = new Book { Id = 1 };
var page = new Page { Id = 1 };
var book = new Word
{
BookId = book.Id, // Ok
PageId = book.Id, // Illegal!
string = "eratosthenes"
};
Yes, you can create types that behave like numeric values but can't be assigned to each other. You can't derive from numeric type, but wrapping one into a struct would be comparable efficient (if that's a concern) or you can add more info (like units). You may be even create generic type if you don't need cross-type operations.
You can see Complex type for full set of operations and interfaces that make type behave very close to regular numbers (including plenty of conversions back and forth as needed).
Some basic class:
class Distance
{
float d;
public Distance(float d)
{
this.d = d;
}
public static Distance operator+(Distance op1, Distance op2)
{
return new Distance(op1.d + op2.d);
}
// ==, !=, Equals and GetHashCode are not required but if you
// need one (i.e. for comparison you need ==, to use values of this
// type in Dictionaries you need GetHashCode)
// you have to implement all
public static bool operator == (Distance op1, Distance op2)
{
return op1.d == op2.d;
}
public static bool operator !=(Distance op1, Distance op2)
{
return op1.d != op2.d;
}
public override bool Equals(object obj)
{
return (object)this == obj || ((obj is Distance) && (obj as Distance)==this);
}
public override int GetHashCode()
{
return d.GetHashCode();
}
// Some basic ToString so we can print it in Console/use in
// String.Format calls
public override string ToString()
{
return $"{d} M";
}
}
Which lets you add values of the same type but will fail to add any other type:
Console.WriteLine(new Distance(1) + new Distance(2)); // "3 M"
// Console.WriteLine(new Distance(1) + 2); // fails to compile
Picking between class and struct for such sample is mostly personal preference, for real usage make sure to know difference between value and reference type before picking one and decide what works for you (struct is likely better for numbers).
More information:
Units of measure in C# - almost - even if you don't go all the way it shows how to make generic numeric type so you can easily create many types without much code (UnitDouble<T> in that post), Arithmetic operator overloading for a generic class in C# - discusses issues you face if you want to go other way and support varying base numeric types (like Distance<float> and Distance<int>).
It turns out my needs were a bit more simple than I thought. What I needed was a unique ID that could not be confused with another unique ID. In the end, I went with a template wrapper for an int.
class Id<T> {
private int id;
public Id(int id) { this.id = id; }
public static implicit operator ID<T>(int value) { return new ID<T>(value); }
public static implicit operator int(ID<T> value) { return value?.id ?? 0; }
public static implicit operator int?(ID<T> value) { return value?.id; }
public static implicit operator ID<T>(int? value)
{
if (value == null) { return null; }
return new ID<T>(value.Value);
}
public override string ToString() { return id.ToString(); }
}
class Book { Id<Book> Id; }
class Page { Id<Page> Id; }
Book.Id cannot be assigned to Page.Id, but either can go back and forth with ints.
I realise now that I've seen this pattern before somewhere, so I guess it's not that original...

C# Operator Overloading, rewriting string?

I'm very fresh to C#
Currently learning Operator overloading
i'm trying to do something like this:
string val = 500; (I can't implicitly)
and then
Number n1 = val;
I manages to get the Number n1 = someintvalue, for instance:
Number n1 = 500;
like this:
public struct Number
{
public int Value { get; set; }
public Number(int Val)
{
Value = Val;
}
public static implicit operator Number(int num)
{
return new Number(num);
}
}
However, when trying to make Number n1 = val; (when val is a string)
I simply cant since the first line cant compile:
string val = 500;
and the following wont work:
public static implicit operator string(int A)
{
return new string(A);
}
because of 1 error which i can not understand
1)User-defined conversion must convert to or from the enclosing type
by the way i get the idea of op overload
underthis specific case of: return new Number(num);
I simply init the ctor
still need some more fundemental understanding
thx ahead!
I presume the function you quote is within the Number class. You have added a conversion operator from an int to a string within that class, which is not legal. You can only add operators that convert to or from the type they're defined in, such as:
public static implicit operator string(Number A)
{
return new string(A.Value);
}
which will fail because string does not have a constructor that takes an int. You could do:
public static implicit operator string(Number A)
{
return A.ToString();
}
But the standard way to "convert" to a string is to overload the ToString method, which the compiler often calls automatically when a conversion to string is requested:
public override string ToString()
{
return Value.ToString();
}

CodeWars C# Kata stumble

"The following code is not executing properly, try to figure out why."
public class CustomMath {
public static int multiply(int a, string b) {
return a * b;
}
}
Here's my solution:
public class CustomMath
{
Int i = 1;
public static int multiply(int a, int b)
{
return a * b;
}
}
I'm still plugging away at it started looking at operator overloading. Still catching the fail so I guess I am still not seeing it or failing to understand something about using operator overloading. Is the operator overloading my only issue or is my return syntax off?
using system;
public class CustomMath
{
public static int operator *(int a, string b)
{
return a * b;
}
}
So I'm looking into binary operators, pretty sure my issue is that I am not expressing the int and string properly.
from the error that you've got you should understand that the function signiture is wrong and you need to change the type of b (string) to be int. so your code would be:
public class CustomMath
{
public static int multiply(int a, int b)
{
return a * b;
}
}
Your operator overload won't work, because in order to overload the multiplication operator, at least one of the operands has to be of a user-defined type.
The thing is, you don't need overloading at all. There are methods in the .NET framework designed specifically to "extract" an integer from a string, which is what you should do before multiplying anything. There are two easy ways of achieving this: int.Parse and int.TryParse. Just take a look at the MSDN documentation to figure out how they work and choose the best in your specific scenario.
And here is int.Parse in action:
string s = "5";
int i = int.Parse(s);
int j = i + 10 // At this point j = 15

Operators and inheritance

My brain has turned to jelly, or I'm having an out of mind experience, or something. I'm tinkering with a class hierarchy that looks a bit like this:
My Money class looks like this:
public abstract class Money
{
public int Amount { get; set; }
public static bool operator ==(Money leftSide, Money rightSide)
{
// Money can only be equal if it is in the same currency.
if (leftSide.GetType() != rightSide.GetType()) return false;
return leftSide.Amount == rightSide.Amount;
}
public static bool operator !=(Money leftSide, Money rightSide)
{
// If the currencies are different, the amounts are always considered unequal.
if (leftSide.GetType() != rightSide.GetType()) return true;
return leftSide.Amount != rightSide.Amount;
}
public static Money operator *(Money multiplicand, int multiplier)
{
var result = multiplicand * multiplier;
return result;
}
public static Dollar Dollar(int amount)
{
return new Dollar(amount);
}
public static Franc Franc(int amount)
{
return new Franc(amount);
}
}
My Dollar operator * looks like this:
public static Dollar operator *(Dollar multiplicand, int multiplier)
{
var result = multiplicand.Amount * multiplier;
return new Dollar(result);
}
Now, if I run this test code, I get a Stack overflow (wahoo!)
{
Money fiveDollars = Money.Dollar(5);
Money timesTwo = fiveDollars*2;
}
I had expected that this would recursively call the subclass (Dollar) operator *, which would return a definite result since (Dollar * int) is defined non-recursively. Since this doesn't work, the alternative is that I have done something dumb. Why doesn't this work? What would be the right way to get this behaviour?
You seem to have left out .Amount
public static Money operator *(Money multiplicand, int multiplier)
{
var result = multiplicand.Amount * multiplier;
return result;
}
The problem is that you expect that you can override operators in derived classes and expect dynamic binding. This is not the way it works in C#. Operators are overloaded and the actual overload is chosen compile-time. This means that the following code is recursive and calls itself:
public static Money operator *(Money multiplicand, int multiplier)
{
var result = multiplicand * multiplier;
return result;
}
Another example where you can see the difference between operator overloading and method overriding is this:
int a = 5;
int b = 5;
Console.WriteLine(a == b); // true
Console.WriteLine(a.Equals(b)); // true
Console.WriteLine((object)a == (object)b); // false
Console.WriteLine(((object)a).Equals((object)b)); // true
In the third case, C# treats a and b as objects instead of integers, so it uses the default == operator that is used for objects: comparing references (in this case the references of boxed integers).
This can make it awkward to define operators on a class hierarchy where you want to redefine the operators in derived classes. It is especially awkward when the behavior depends on the combination of both operands, since C# (and most other OOP languages) lacks support for multiple dispatch. You can solve this by using the visitor pattern, but I think in this case you should reconsider if using subclasses for each currency is the best solution.

Categories

Resources