public class Racional<T>
{
private T nominator;
private T denominator;
public T Nominator
{
get { return nominator; }
set { nominator = value; }
}
public T Denominator
{
get { return denominator; }
set { denominator = value; }
}
public Racional(T nominator, T denominator)
{
this.nominator = nominator;
this.denominator = denominator;
}
public static Racional<int> operator *(Racional<int> a, Racional<int> b)
{
return ((int)(a.nominator + b.nominator, a.denominator + b.denominator));
}
public override string ToString()
{
return "(" + this.nominator + " " + this.denominator + ")";
}
}
I'm interested in this part :
public static Racional<int> operator *(Racional<int> a, Racional<int> b)
{
return ((int)(a.nominator + b.nominator, a.denominator + b.denominator));
}
What's wrong:
One of the parameters of a binary operator must be the containing type
How I can normaly code this part for mathematic operations?
The reason your code doesn't compile is explained by the compiler error. The containing type is a generic type definition, and a generic type constructed from such a type is not considered to be the same type.
I have a few questions:
Why must the Rational type be generic? A rational number is defined as a number that can be expressed as the quotient / fraction of two integers (where the denominator is not 0). Why not make the type non-generic and simply use int throughout? Or do you intend that the type be used for other integral types such as long and BigInteger? In that case, consider using something like Aliostad's suggestion if you want some code-sharing mechanism.
Why do you want the product of two rational numbers to be the equal to the sum of their numerators over the sum of their denominators? That doesn't make sense to me.
In any case, you appear to want to be able to 'generically' add two instances of an 'addable' type. Unfortunately, there currently isn't any way to express a 'has a suitable addition operator' constraint in C#.
Method #1: One workaround for this in C# 4 is to use the dynamic type to give you the desired "virtual operator" semantics.
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = (dynamic)a.Nominator + b.Nominator;
var denominatorSum = (dynamic)a.Denominator + b.Denominator;
return new Racional<T>(nominatorSum, denominatorSum);
}
The operator will throw if the type doesn't have a suitable addition operator.
Method #2: Another (more efficient) way is to use expression-trees.
First, create and cache a delegate that can perform the addition by compiling the appropriate expression:
private readonly static Func<T, T, T> Adder;
static Racional()
{
var firstOperand = Expression.Parameter(typeof(T), "x");
var secondOperand = Expression.Parameter(typeof(T), "y");
var body = Expression.Add(firstOperand, secondOperand);
Adder = Expression.Lambda<Func<T, T, T>>
(body, firstOperand, secondOperand).Compile();
}
(The static constructor will throw if the type doesn't have a suitable addition operator.)
Then employ it in the operator:
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = Adder(a.Nominator, b.Nominator);
var denominatorSum = Adder(a.Denominator, b.Denominator);
return new Racional<T>(nominatorSum, denominatorSum);
}
The issue here is you are defining an operator for Racional<int> in the class Racional<T>. This is not possible. The types are not the same, you can only define operator for Racional<T>.
Generics cannot express generalization of operators since they are defined only for a certain types. Solution is to create a class and inherit from Racional<int>:
public class IntRacional : Racional<int>
{
public static Racional<int> operator +(IntRacional a, IntRacional b)
{
return new Racional<int>()
{
Nominator = a.Nominator + b.Nominator,
Denominator = a.Denominator + b.Denominator
};
}
}
To solve your issue, you need to provide conversion functions from T to some type where operator+ is defined and vice versa. Assuming Int64 is big enough in most cases, this can be done this way:
public class Racional<T>
{
private T nominator;
private T denominator;
static Converter<T,Int64> T_to_Int64;
static Converter<Int64,T> Int64_to_T;
public static void InitConverters(Converter<T,Int64> t2int, Converter<Int64,T> int2t )
{
T_to_Int64 = t2int;
Int64_to_T = int2t;
}
public T Nominator
{
get { return nominator; }
set { nominator = value; }
}
public T Denominator
{
get { return denominator; }
set { denominator = value; }
}
public Racional(T nominator, T denominator)
{
this.nominator = nominator;
this.denominator = denominator;
}
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
return new Racional<T>(
Int64_to_T(T_to_Int64(a.nominator) + T_to_Int64(b.nominator)),
Int64_to_T(T_to_Int64(a.denominator) + T_to_Int64(b.denominator)));
}
// By the way, should this not be * instead of + ???
//
// public static Racional<T> operator *(Racional<T> a, Racional<T> b)
// {
// return new Racional<T>(
// Int64_to_T(T_to_Int64(a.nominator) * T_to_Int64(b.nominator)),
// Int64_to_T(T_to_Int64(a.denominator) * T_to_Int64(b.denominator)));
// }
public override string ToString()
{
return "(" + this.nominator + " " + this.denominator + ")";
}
}
Of course, this has the drawback that you must provide the initialization of those converters somewhere at the program start, should look like this:
Racional<int>.InitConverters(x => (Int64)x, y => (int)y);
In a real program, you may know which possible replacements for T you are going to use. So one can provide those 3 or 4 calls in a static constructor like this:
public static Racional()
{
Racional<int>.InitConverters(x => (Int64)x, y => (int)y);
Racional<short>.InitConverters(x => (Int64)x, y => (short)y);
Racional<Int64>.InitConverters(x => (Int64)x, y => (Int64)y);
}
should be sufficient in most cases. Note that this converter initialization is repeated for all 3 types 3 times again, re-initializing the conversion functions multiple times again. In practice this should not make any trouble.
Related
I have a generic Quantity<T> class for managing physical quantities, looks like this:
public class Quantity<T> where T : Unit
{
public Quantity(double value, T unit)
{
this.OriginalUnit = unit;
this.Value = unit.ConvertBack(value);
}
...
}
The Unit class manages the different units a quantity can be in, but it isn't really relevant for my question.
What I would like to do is define operators in the generic Quantity<T> class like this:
public static Quantity<ElectricResistanceUnit> operator /
(Quantity<ElectricVoltageUnit> q1, Quantity<ElectricCurrentUnit> q2)
{
return new Quantity<ElectricResistanceUnit>(q1.Value / q2.Value, ElectricResistanceUnit.Ohm);
}
But this does not compile ("one of the parameters of a binary operator must be the containing type"). Is there any way around this?
One way this works, that is not really a solution for me, is the following:
public class ElectricVoltage : Quantity<ElectricVoltageUnit>
{
public static ElectricResistance operator /(ElectricVoltage q1, ElectricCurrent q2)
{
return new ElectricResistance(q1.Value / q2.Value, ElectricResistanceUnit.Ohm);
}
}
public class ElectricCurrent : Quantity<ElectricCurrentUnit>
{
}
public class ElectricResistance : Quantity<ElectricResistanceUnit>
{
}
The problem with this is: I would have to define an empty derived class for all my Units (which is a LOT), plus this makes me inflexible in composed classed (can't cast Quantity<ElektricResistanceUnit> to ElectricResistance).
Does someone know a more elegant way of solving this?
The only way to avoid empty classes in your case I can see is to do something like that:
interface INumeric<T>
{
T Add(T num);
T Substract(T num);
T Multiply(T num);
T Divide(T num);
}
class Quantity<T> where T : INumeric<T>
{
public T Value { get; set; }
public static Quantity<T> operator + (Quantity<T> left, Quantity<T> right)
{
return new Quantity<T>() { Value = left.Value.Add(right.Value) };
}
public static Quantity<T> operator - (Quantity<T> left, Quantity<T> right)
{
return new Quantity<T>() { Value = left.Value.Substract(right.Value) };
}
public static Quantity<T> operator / (Quantity<T> left, Quantity<T> right)
{
return new Quantity<T>() { Value = left.Value.Divide(right.Value) };
}
public static Quantity<T> operator * (Quantity<T> left, Quantity<T> right)
{
return new Quantity<T>() { Value = left.Value.Multiply(right.Value) };
}
}
Then you have to implement INumeric<T> in Unit and each unit can have it's own implementation of this methods
public struct DecimalOrNaN
{
public decimal Value;
public bool isNaN;
public DecimalOrNaN (double D)
{
if (Double.IsNaN(D))
{
Value = default(decimal);
isNaN = true;
}
else
{
Value = (decimal)D;
isNaN = false;
}
}
public DecimalOrNaN(decimal D)
{
Value = D;
isNaN = false;
}
public implicit operator DecimalOrNaN(double D)
{
return new DecimalOrNaN(D);
}
public implicit operator DecimalOrNaN(decimal D)
{
return new DecimalOrNaN(D);
}
public DecimalOrNaN operator *(int I, DecimalOrNaN D)
{
return new DecimalOrNaN(D.Value * I);
}
}
I have this struct (let's just call it DON) here which stores decimals, but has an option to have "Not a Number" in it, which regular decimal lacks. I can add the needed implicit conversions myself, but i also need it to be able to add, subtract and multiply with other DONs as well as with ints, doubles and decimals. Do I have to create each operator with each variation of parameters (int + DON, DON + int, int * DON,DON * int and so on) myself or is there a better way of doing it?
My suggestion would be to use the nullable type: decimal?. This will allow you to assign NULL to the variable to indicate it's not a number.
Documentation for this feature of the language is available here: http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx
I have a class called GenericItem (first time using generics), suppose i wanted to multiply two items if they were of the type integer, as you can see I am trying it in the method returnCounterMultiply, but it does not allow me to multiply them although i am trying to convert them and also checking if they are of type integer.
namespace Components
{
public class GenericItem<T>
{
private T data;
private T counter;
public T Data
{
get { return data; }
set { data = value; }
}
public GenericItem(){}
public GenericItem(T _data)
{
data = _data;
}
public T returnCounterMultiply(T value)
{
int c = 0;
int d = 0;
if (counter.GetType() == typeof(int) && value.GetType() == typeof(int))
{
//cant multiply two of type T, why if i am converting to int?.
return (T)Convert.ChangeType(counter, typeof(Int32)) * (T)Convert.ChangeType(value, typeof(Int32));
}
return value;
}
}
}
I would appreciate some explanation on this as this is the first time I am working on it (this is just a sample class for understanding this GENERICS INTRO and this GENERICS CLASSES, but still having trouble understanding it.
I don't see what your trying to achieve, but if you have to do it I think you have to use an interface:
public interface IMultiplyable<T>
{
T Multiply(T x);
}
public class Int : IMultiplyable<Int>
{
private int _data { get; set; }
public Int(int data)
{
_data = data;
}
public Int Multiply(Int x)
{
return new Int(_data * x._data);
}
public override string ToString()
{
return _data.ToString();
}
}
public class GenericItem<T> where T : IMultiplyable<T>
{
private T data;
private T counter;
public T Data
{
get { return data; }
set { data = value; }
}
public GenericItem() { }
public GenericItem(T _data)
{
data = _data;
}
public T returnCounterMultiply(T value)
{
return Data.Multiply(value);
}
public override string ToString()
{
return Data.ToString();
}
}
Usage:
var a = new GenericItem<Int>(new Int(4));
MessageBox.Show(a.returnCounterMultiply(new Int(5)).ToString()); //20
In my opinion, using generics in this case is an overkill.
It would be nice that generic constraints support something like:
// T parameter is a type which overloads "+" operator...
where T : +
In your concrete case, I would argue you're going in the wrong way. Why don't you just create a class to implement such math operations where properties are typed as int?
Generics work better when T parameter (or any other parameter, of course...) can be constrained to receive types which have:
A public parameterless constructor.
Inherits or implements a class/interface
You need to constraint that T must be a class and not a struct...
When you go into a problem when using generics requires a type conversion, I believe you defeated the point of generics!
You can do something like this:
public class GenericItem<T>
{
private T data;
public T Data
{
get { return data; }
set { data = value; }
}
public GenericItem(){}
public GenericItem(T _data)
{
data = _data;
}
private Dictionary<Type, Delegate> operations =
new Dictionary<Type, Delegate>()
{
{ typeof(int), (Func<int, int, int>)((x, y) => x * y) },
{ typeof(string), (Func<string, string, string>)((x, y) => x + " " + y) },
};
public T returnCounterMultiply(T value)
{
if (operations.ContainsKey(typeof(T)))
{
var operation = (Func<T, T, T>)(operations[typeof(T)]);
return operation(data, value);
}
return value;
}
}
You just need to define, in the dictionary, one operation per valid types you're going to want to use and it just works without any converting of types (except to cast to the Func).
I had these test results:
var gii = new GenericItem<int>(42);
var xi = gii.returnCounterMultiply(2);
// xi == 84
var gis = new GenericItem<string>("Foo");
var xs = gis.returnCounterMultiply("Bar");
// xs == "Foo Bar"
Your problem has nothing to do with generics but with basic C# casting priority:
//cant multiply two of type T, why if i am converting to int?.
return
(T)Convert.ChangeType(counter, typeof(Int32))
*
(T)Convert.ChangeType(value,typeof(Int32));
You do not multiply int but T - and T being a generic type you can only use methods that are ddefined in your generics contraint, which you have none, so no multiply on it.
If you want to multiply int, then do so:
(T) (
((Int32)Convert.ChangeType(counter, typeof(Int32)))
*
((Int32)Convert.ChangeType(value,typeof(Int32)))
);
See the difference?
Basically in your code you deal with T in the multiplication, here I deal with Int32. And factually if T is a Int32 (as you tested before in the IF statement) you can just skip the convert and cast:
(T) (
((Int32)counter)
*
((Int32)value)
);
Now, generics are a bad example for maths as you can not use operations on generics - sadly. This is an abuse of the concept, but I take it was meant as a learning exercise and thus focused on that part on my answer.
I too tried this once and had to find out that there is no pretty way to do it with generics. You cannot do it as generic as in C++.
As an alternative, you may wrap your data types and use a common interface:
interface IMathOps
{
object Value { get; }
void Add(IMathOps other);
// other methods for substraction etc.
}
class IntWrapper : IMathOps
{
public int value;
public void Add(IMathOps other)
{
if(other is IntWrapper)
{
this.value += (int)other.Value;
}
}
public object Value { get { return this.value; } }
}
// class FloatWrapper : IMathOps ...
I think you should use where (generic type constraint). So it will give error at compile time if T is not int.
public T returnCounterMultiply(T value) where T : int
{
int c = 0;
int d = 0;
return c*d;
}
I need to return a method in an operator function.
public int Add()
{
return 1;
}
public static int operator +()
{
return Add;
}
I will need to do this for a multiply, subtract and divide operator/function too.
Thanks
You can't declare parameterless operators. You can declare an operator to return an appropriate delegate - e.g. Func<int> - but it would be a pretty odd thing to do, IMO.
If you can tell us more about what you're trying to achieve, we can probably help you to work out a cleaner design.
Here's a pretty strange example overloading the unary + operator:
using System;
class Weird
{
private readonly int amount;
public Weird(int amount)
{
this.amount = amount;
}
private int Add(int original)
{
return original + amount;
}
// Very strange. Please don't do this.
public static Func<int, int> operator +(Weird weird)
{
return weird.Add;
}
}
class Test
{
static void Main(string[] args)
{
Weird weird = new Weird(2);
Func<int, int> func = +weird;
Console.WriteLine(func(3));
}
}
EDIT: If you're just trying to implement a Rational type, you're more likely to want:
public struct Rational
{
// Other members
public Rational Add(Rational other)
{
...
}
public static Rational operator +(Rational left, Rational right)
{
return left.Add(right);
}
}
This is what you SEEM to be trying to do, but your example makes it difficult to tell. So, from your comments in other answers it looks like you want to add, subtract, multiply, divide Rational numbers, which means the result should be a Rational as well (not an int).
Thus, you could define each of your methods, then implement operators to call those. The operators are always static, thus you'd need to check for null and handle as appropriate (in this case, I'll just throw ArgumentNullException):
public class Rational
{
public Rational Add(Rational other)
{
if (other == null) throw new ArgumentNullException("other");
return // <-- return actual addition result here
}
public static Rational operator +(Rational left, Rational right)
{
if (left == null) throw new ArgumentNullException("left");
return left.Add(right);
}
public Rational Subtract(Rational other)
{
if (other == null) throw new ArgumentNullException("other");
return // <-- return actual subtraction result here
}
public static Rational operator -(Rational left, Rational right)
{
if (left == null) throw new ArgumentNullException("left");
return left.Subtract(right);
}
public Rational Multiply(Rational other)
{
if (other == null) throw new ArgumentNullException("other");
return // <-- return actual multiplication result here
}
public static Rational operator *(Rational left, Rational right)
{
if (left == null) throw new ArgumentNullException("left");
return left.Multiply(right);
}
public Rational Divide(Rational other)
{
if (other == null) throw new ArgumentNullException("other");
return // <-- return actual division result here
}
public static Rational operator /(Rational left, Rational right)
{
if (left == null) throw new ArgumentNullException("left");
return left.Divide(right);
}
}
Simple. Just call the Add method:
return Add();
C Sharp - Lesson 18: Overloading Operators
I don't think you can overload the + operator for int's! You would have to create your own wrapper class or struct instead:
public struct MyInt
{
private int _value;
public MyInt(int value)
{
_value = value;
}
public int Value
{
get { return _value; }
}
public static MyInt operator +(MyInt a, MyInt b)
{
return new MyInt(a._value + b._value);
}
public static implicit operator MyInt(int intValue)
{
return new MyInt(intValue);
}
public static explicit operator int(MyInt x)
{
return x.Value;
}
}
Then you are free to do with '+' what ever you want to do with it.
The implicit operator automatically converts int's to MyInt. So you could assign like this: MyInt x = 7;
The explicit operator converts MyInt's to int's like: int i = (int)x; where x is a MyInt.
Can I overload operators for class A in class B in C#? For example:
class A
{
}
class B
{
public static A operator+(A x, A y)
{
...
}
}
No; one of the parameters must be the containing type.
From section §10.10.2 of the language specification (version 4.0):
The following rules apply to binary operator declarations, where T denotes the instance type of the class or struct that contains the operator declaration:
• A binary non-shift operator must take two parameters, at least one of which must have type T or T?, and can return any type.
You should think about why. Here's one reason.
class A { }
class B { public static A operator+(A first, A second) { // ... } }
class C { public static A operator+(A first, A second) { // ... } }
A first;
A second;
A result = first + second; // which + ???
Here's another:
class A { public static int operator+(int first, int second) { // ... } }
Assume this allowed for a moment.
int first = 17;
int second = 42;
int result = first + second;
Per the specification for operator overload resolution (§7.3.2), A.+ will have precedence over Int32.+. We've just redefined addition for ints! Nasty.
No, you can't. error CS0563: One of the parameters of a binary operator must be the containing type
"In each case, one parameter must be the same type as the class or struct that declares the operator" quote from
Documentation on overloading operators.
Generally saying NO, but you can do something like following, if it helps :)
class A
{
public static A operator +(A x, A y)
{
A a = new A();
Console.WriteLine("A+"); // say A
return a;
}
}
class B
{
public static A operator +(A x, B y)
{
A a = new A();
Console.WriteLine("return in:A,B in out:A in class B+"); // say B
return a;
}
public static A operator +(B x, B y)
{
A a = new A();
Console.WriteLine("return in:B,B in out:A in class B +");
return a;
}
// and so on....
}
B b = new B();
A a = new A();
A a1 = new A();
B b1 = new B();
a = b + b1; // here you call operator of B, but return A
a = a + a1; // here you call operator of A and return A
To understand your problem, can i ask why you want to do that? :)