C++ template use constraint by signature,It's very flexible to programmer but complex for complier, and at most time programmer can not get clear error message from complier if error occur. C# generic use constraint by type,complier is relaxed, but it is very limited and even sometime tedious to programmer. Is there a way to get merits of both
(NOTE: I think the all-important purpose of develope tools is to let programmer relax, not the complier !!! Anders Hejlsberg spend so many time add some useless feathers(Except LING) to C# 3.0 to some extent,but he do not spend enough time to improve C#' most basical and important feathers: generic[Constraint, dynamic Constraint, Specilization and so on ] and AOP[G# ], let programmers still in hell...[write and maintance similar code again and again, and sometime, think out many complex architect that is unnecessary in order to use c#'s bad designed generic])
(BUT I'm not Anders Hejlsberg, Even i do not know how to contract with him. BUT hope him can read this thread. and rescue programmers like me.)
Maybe the following way can achieve this purpose :
//First add a keyword "constrant" to define constrant, so the meta data can be treat same as common class.
//For all types
constrant TAll : 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 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>();
}
}

C# Generic Constraint Improve Way?
Tim Cools
Thanks first!
I'm agree what u said about C++ templates, that should be known to me more than several years ago , BUT maybe u misunderstand me and something about C# generic.
First,I just want to combine the C++ templates and C# generic, want to Add the Flexibiity of C++ templates to C# generic, to get the merits of both.
Second, You said "All you've done is limit your generic class GenericClass to instances and derived types of TAll, TClass and TStruct,Constraints as they exist today can do the same thing", really you just can do so for your new types, how to do with types that already exists in .net framework, your old codes, and other codes you can use where cause to require a static method, a operator overload, a constructor with special parameters and other requirement you can NOT!
Today, even u want to implement a simple generic class that want the Type parameter to have a "public static bool operator +(TStruct t1, TStruct t2)" method constrant,you have no way.
Anders Hejlsberg give us a factory pattern such as GenericClass(Calcultor<T> calcultor) to achieve this(http://blogs.msdn.com/ericgu/archive/2003/11/14/52852.aspx),It's very ugly and tedious and complex, and it will be much more tedious and complex if we want to implement more complex function. we must implement it even for .net bulltin type such as int, decimal and so on... So we have to add many complex and repetitious structure to achieve purpose like this that should have been unnecessary if Anders Hejlsberg give us a better design on constrants just like what i write.
by the way, partial or full specialization is just the second purpose compared to constrants.
j_johnso
It is important to remember that C++ templates are not the same thing, and do not serve the same purpose, as C#/.NET generics. Although they look similar and people often think of them as the same they are not. C++ templates are true templates. They define the skeleton of a new class or function. The compiler, at compile time, will generate a new class or function that takes any type given to it and substitutes it into the template. It is basically a typed macro in my mind. C++ templates have the following issues to me.
- Each time a new type is used in a template a new, concrete type is created from the template skeleton and therefore more space is taken up.
- I think the C++ community went overboard with metaprogramming. I'm sure much of this is useful but I think many in the community lost site of the trees for the forest. Many templates are so hard to read, even for someone who understands templates, that I don't trust them. Would you use code that you couldn't understand It seems that many in the community have accomplished things with templates just to prove they could moreso than as a useful addition to the programming realm.
- The template skeleton must be stored in the header file because the compiler must have access to the entire definition at compilation time.
- As you mentioned compiler errors for templates are notoriously difficult. This is because the compiler has to identify to you the place within the template definition where the error occurred and the actual declaration that caused the template to fail in the first place.
- Templates must support all types. What I mean by this is that you can't limit a template to a specific type. For example if you create a template class called Matrix there is nothing to prevent me from trying to instantiate it with a string class. Of course if you use methods or operators that are only valid for numbers then a compiler error would occur but otherwise I could do it.
Generics on the other hand are not true templates. They instead define a class or function that accepts arbitrarily typed objects and operates on them. The type is limited by the constraints. The compiler creates a single type for the generic class in the metadata. When you use the generic type with reference types a single, concrete class is created to work with the reference type (and any other reference type as well). Value types will each get their own concrete class. In this way a generic class can save space over the C++ templates (exception for value types). Another advantage of generics is that you can more strongly control what types are valid in the generic through constraints.As a user of both C++ templates and C#/.NET generics I have found generics to be easier to use, more maintainable, more efficient and overall a better design. I do miss the specialization of C++ templates but I have yet to run across a problem I couldn't work around. C++ templates are more general purpose than generics and with metaprogramming you can really do a lot of compile-time code generation but I personally don't find that justification for the general template language feature added to C++.
IMHO,
Michael Taylor - 12/11/05