(SOS) Strongly Request: Improve generic constraint in C#3.0 !!!
// Strongly Request: Improve generic constraint in C#3.0
/**********************************************************************************************************************************/
/* Now, in order to write a GenericType that support simple Arithmetics like "+ - * /" have to write like like the following
* You can see,The code is very ugly and troublesome, the performance is slow, and have to write Constraint for every class not under control
/**********************************************************************************************************************************/
public interface IArithmetics<T>
{
T Add(T a, T b);
T Subtract(T a, T b);
T Multiply(T a, T b);
T Divide(T a, T b);
}
public class GenericType<T, TConstraint>
where TConstraint : IArithmetics<T>, new()
{
private T _Value1;
private T _Value2;
private static readonly TConstraint _Constraint = new TConstraint();
#region Constructors
public GenericType(T value1, T value2)
{
this._Value1 = value1;
this._Value2 = value2;
}
#endregion
public static GenericType<T, TConstraint> operator +(GenericType<T, TConstraint> value1, GenericType<T, TConstraint> value2)
{
T valueSum1 = _Constraint.Add(value1._Value1, value2._Value1);
T valueSum2 = _Constraint.Add(value1._Value2, value2._Value2);
return new GenericType<T, TConstraint>(valueSum1, valueSum2);
}
// Other methods go here...
}
//In oder to use short,int and so on, have to write Int16Constraint,Int32Constraint and so on,endless and troublesome!
public struct Int32Constraint : IArithmetics<int>
{
#region IArithmetics<int> Members
public int Add(int a, int b) { return a + b; }
public int Subtract(int a, int b) { return a - b; }
public int Multiply(int a, int b) { return a * b; }
public int Divide(int a, int b) { return a / b; }
#endregion
}
//public struct Int16Constraint : IArithmetics<int> { /*....*/}
//public struct Int64Constraint : IArithmetics<long> { /*....*/}
/**********************************************************************************************************************************/
/* BUT if u can provide a new key 'constrant' like the following, the life will become good
/* constrant only used to provide compiler checking and intellisense.
/**********************************************************************************************************************************/
public constrant ArithmeticsConstraint<T>
{
public static T operator +(T value1, T value2);
public static T operator -(T value1, T value2);
public static T operator *(T value1, T value2);
public static T operator /(T value1, T value2);
}
public class GenericType<T>
where T : ArithmeticsConstraint<T>
{
private T _Value1;
private T _Value2;
#region Constructors
public GenericType(T value1, T value2)
{
this._Value1 = value1;
this._Value2 = value2;
}
#endregion
public static GenericType<T> operator +(GenericType<T> value1, GenericType<T> value2)
{
T valueSum1 = value1._Value1 + value2._Value1;
T valueSum2 = value1._Value2 + value2._Value2;
return new GenericType<T, TConstraint>(valueSum1, valueSum2);
}
// Other methods go here...
}
/**********************************************************************************************************************************/
/* The above is just simple case, the following are the more complex case.
/**********************************************************************************************************************************/
constrant TAllType : ISomeInterface,ISomeInterface2
{
//Constructors
public TAllType();
public TAllType(int i);
//Methods
public static bool operator ==(TClass t1, TClass t2);
public static bool operator +(TClass t1, TClass t2);
public void Method1();
public void Method2(TClass t, int i);
//Properties
public int Property1{get;set;}
public int this[int i]{get;}
}
//For class
class constrant TClass : ISomeInterface,ISomeInterface2,...
{
//Constructors
public TClass();
public TClass(int i);
//Methods
public static bool operator ==(TClass t1, TClass t2);
public static bool operator +(TClass t1, TClass t2);
public void Method1();
public void Method2(TClass t, int i);
//Properties
public int Property1{get;set;}
public int this[int i]{get;}
}
//For struct
struct constrant TStruct: ISomeInterface,ISomeInterface2,...
{
//Constructors
public TStruct();
public TStruct(int i);
//Static Methods
public static bool operator ==(TStruct t1, TStruct t2);
public static bool operator +(TStruct t1, TStruct t2);
public void Method1();
public void Method2(TStruct t, int i);
//Properties
public int Property1{get;set;}
public int this[int i]{get;}
}
//GenericClass use TClass,TStruct as normal class,compiler can give clear error message
public class GenericClass<TAll,TClass,TStruct>
//Note here use constrant class or struct directly
//"where" statement is not needed now
{
public void sample()
{
//here just treat TAll, TClass,TStruct as normal type, it's simple for compiler.
TAll all=new TAll(10);
TClass refObj = new TClass();
TClass refObj2 = new TClass(1);
TClass refObj3 = refObj + refObj2;
TStruct valueObj = new TStruct(100);
TStruct valueObj2 = new TStruct(10);
if (valueObj == valueObj2)
{
valueObj.Method1();
valueObj2.Method2();
}
int i=refObj3.Property1;
int j=valueObj2[0];
//if can support dynamic constrant,that's better, runtime can produce correct il for each type
#if(typeof(TAll)==typeof(int))
{
//do something for int ....
}
#else if(typeof(TAll)==typeof(decimal))
{
//do something for decimal ....
}
#else
{
}
}
}
public class UseGenericClass
{
public void Test()
{
//Compiler will check:
//RealType includes all signatures of TAll, but do not force RealType inherited from TAll;
//RealClass is class, includes all signatures of TClass, but do not force RealClass inherited from TClass;
//RealStruct is Struct, includes all signatures of TStruct
GenericClass<RealType, RealClass,RealStruct> obj=new GenericClass<RealClass,RealValue>();
}
}

