Introduction
This is an article about operator overloading with generics using inheritance to allow the use of C# operators (C# 2005). Normally, the C# compiler does not allow us to use C# operators on a type parameter. For example, say you have some generic code, and you are doing some processing, such as adding the types, then it would be nice to use the '+
' operator.
class CMyGenericClass<T>
{
public T TestUsingOperatorsOnT(T _one, T _two)
{
T tTemp = (_one + _two);
return tTemp;
}
}
Compiling this code results in the compiler error:
Operator '+' cannot be applied to operands of type 'T' and 'T'
Now, there may be good reasons why C# 2005 does not allow operations to be used on generic parameters. The most likely reason is that operator code is not truly 'generic'. However, there may be cases where it would be nice to use an operator...
Background
This article was inspired by the book "Pro C#2005 and the .NET 2.0 Platform", by Andrew Troelsen (an excellent book...), where I learned about the compiler restriction (that generic code could not use operators on the parameter type).
This seemed a bit restrictive to me, so I figured there must be a way around it. This is a fairly simple way around it.
The Code
We can circumvent this restriction, by creating an abstract
type, which has the desired operators. The actual implementation of the operator will be an abstract
method, which our type 'T
' must provide:
abstract class CMyOperations
{
...
public abstract CMyOperations AddMyOperations(CMyOperations _ITwo);
public static CMyOperations operator +(CMyOperations _IOne, CMyOperations _ITwo)
{
return _IOne.AddMyOperations(_ITwo);
}
...
}
The implementation for these operators will be provided by our type 'T
', here CMyComplexNumber
:
class CMyComplexNumber : CMyOperations
{
public override CMyOperations AddMyOperations(CMyOperations _ITwo)
{
}
};
In our generic class, we can force the type 'T
' to provide the desired operations, by using the 'where
' keyword:
class CMyGenericClass<T> where T : CMyOperations
{
...
}
The 'where
' keyword here means that the type 'T
' must be derived from CMyOperations
. Because CMyOperations
is abstract
, 'T
' must provide the implementation for the required operations. To sum it up by example:
abstract class CMyOperations
{
public abstract CMyOperations AddMyOperations(CMyOperations _ITwo);
public static CMyOperations operator +(CMyOperations _IOne, CMyOperations _ITwo)
{
return _IOne.AddMyOperations(_ITwo);
}
}
class CMyComplexNumber : CMyOperations
{
private int iIValue = 0;
private int iJValue = 0;
public CMyComplexNumber(int _iIValue, int _iJValue)
{
iIValue = _iIValue;
iJValue = _iJValue;
}
public override CMyOperations AddMyOperations(CMyOperations _ITwo)
{
if(_ITwo is CMyComplexNumber)
{
CMyComplexNumber numberNew = new CMyComplexNumber(0, 0);
CMyComplexNumber number2 = _ITwo as CMyComplexNumber;
numberNew.iIValue = iIValue + number2.iIValue;
numberNew.iJValue = iJValue + number2.iJValue;
return numberNew;
}
else
{
System.Diagnostics.Debug.Assert(false,
"CMyComplexNumber.CMyOperations.AddMyOperations()
was invoked for an unsupported parameter type.");
}
return null;
}
public override string ToString()
{
return String.Format("{0}i {1}j", iIValue, iJValue);
}
}
We can now write generic code, which uses C# operators on the type parameter 'T
':
class CMyGenericClass<T> where T : CMyOperations
{
public T TestUsingOperatorsOnT(T _one, T _two)
{
T tTemp = (T)(_one + _two);
return tTemp;
}
};
Points of Interest
- There were a few other ways I tried to allow generic code to use operators - thought about using interfaces - however, we cannot have operators inside interfaces.
- Using the '
where
' keyword is an indirect way of specifying operator constraints on the type 'T
'.
History
- Submitted on 1st October, 2006
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.