Are generics in C# treated the same way as in C++? [duplicate] - c#

This question already has answers here:
What are the differences between Generics in C# and Java... and Templates in C++? [closed]
(13 answers)
C# generics compared to C++ templates [duplicate]
(5 answers)
Closed 9 years ago.
I know in C++, generics don't actually exist, but you can simulate it with the use of template. When you build your code, the compiler pre-processes the code and generates a new code with the generic values replaced for the actual values that were specified in the object declaration and then is this new code which is really compiled. For instance, let's say we have the class A as follows:
template<class T>
class A
{
T f();
};
and then somewhere else in the code we have A<int> a;. The actual code that is compiled would be:
class A
{
//Replaces T by int in the pre-processing
int f();
};
After this whole introduction, lets get to the point.
My questions are:
Does C# treats generics the same way as C++? If not, how then?
Are they special types?
Are they resolved in run-time or in compilation-time?
How much space is reserved for generic types in the Activation Register?

This is a very broad topic and can better be explained by:
http://msdn.microsoft.com/en-us/library/c6cyy67b.aspx
To sumarize (from MSDN article linked above):
C# generics do not provide the same amount of flexibility as C++
templates. For example, it is not possible to call arithmetic
operators in a C# generic class, although it is possible to call user
defined operators.
C# does not allow non-type template parameters, such as template
C {}.
C# does not support explicit specialization; that is, a custom
implementation of a template for a specific type.
C# does not support partial specialization: a custom implementation
for a subset of the type arguments.
C# does not allow the type parameter to be used as the base class for
the generic type.
C# does not allow type parameters to have default types.
In C#, a generic type parameter cannot itself be a generic, although
constructed types can be used as generics. C++ does allow template
parameters.
C++ allows code that might not be valid for all type parameters in
the template, which is then checked for the specific type used as the
type parameter. C# requires code in a class to be written in such a
way that it will work with any type that satisfies the constraints.
For example, in C++ it is possible to write a function that uses the
arithmetic operators + and - on objects of the type parameter, which
will produce an error at the time of instantiation of the template
with a type that does not support these operators. C# disallows this;
the only language constructs allowed are those that can be deduced
from the constraints.
In general, although they share similar syntax and uses is most cases, there are many large differences in usage and capabilities.

There is a misunderstanding regarding how C++ templates are resolved. In C++, templates are processed two times (note: the term "pre-processed" is reserved to the Preprocessor, which has nothing to do with templates at all).
On the first processing time, non-dependent names are resolved, whereas dependent names are not resolved:
int x;
template <typename T> foo() {
x; // <-- resolved in phase 1
T::x; // resolved in phase 2, depends on "T"
}
Phase 2 is entered upon instantiation. E.g.:
struct Frob {
int x;
};
int main () {
foo<Frob>();
} // <-- instantiation happens right before the '}'
Also, C++ templates are instantiated lazily, on a per-function basis. This means that not everything in a class template must be resolvable. Only functions actually used are instantiated, which means phase 2 is only entered for used member functions.
This makes templates more versatile than C# style generics: When you instantiate a class template, the instantiated-upon type only has to support a subset of the template.
In C#, generics are resolved eagerly. The "instantiated-upon" type has to support everything the generic class only potentially uses, which puts rather stringent limits on the versatility.
You know already, but both are really distinct concepts. Generics are a runtime construct, and with reflection and self-modifying code, the C# language has to be very defensive w.r.t. resolvability. Templates are a compile time construct (note: not _preprocessing construct!), supporting Turing-complete meta-programming with both type- and non-type-arguments and a powerful compromise between eager and lazy instantiation.
Both have their features.

The implementation of .NET generics is something of a mix.
When the generic class is compiled into MSIL, it's compiled into a single generic type definition.
When clients use the generic class, the .NET runtime compiles separate copies of the class's machine code for simple type parameters (bool, int, etc.) but separate code isn't generated for different object types; they all share the code for Object.

Related

Infer nesting generic type parameter [duplicate]

This question already has answers here:
Why must I provide explicitly generic parameter types While the compiler should infer the type?
(3 answers)
Closed 9 years ago.
I've noticed that the C# compiler doesn't infer second generic parameter.
Example:
C++ template code: (yea I know that templates don't work like generics)
class Test {
public:
template <class T,class V>
T test(V v) {
//do something with v
return T();
}
};
int i = 0;
Test t = new Test();
double j = t.test<double>(i); //infers V as int
The templates (and generics) can't infer return type, so in C++ I give it the first template parameter, and the second template parameter is inferred from the variable type.
Now, same example in C#:
class Test {
public T test<T,V>(V v) where T: new() {
//do something with v
return new T();
}
};
int i = 0;
Test t = new Test();
double j = t.test<double>(i); //Error Using the generic method 'Test.test<T,V>(V)' requires '2' type arguments
But if i use 1 type, I don't have to explicitly specify the type:
class Test {
public V test<V>(V v) where V: new() {
return new V();
}
};
int i = 0;
Test t = new Test();
int j = t.test(i); //OK infers V as int.
So, why can't C# generics infer the second type (while in c++ templates it clearly can) ?
I'm sure it's designed that way (I doubt they the .Net team overlooked this), so why is it designed this way that I must explicitly specify both types?
Edit:
From the discussions we had in the answers so far, both languages support overloading by number of template parameters.
So again, why is C# designed this way ? What's different in the language implementation that doesn't allow to explicitly declare only one parameter ?
C# has been designed to be a slightly less brain-bending language than C++.
In particular, I don't think it's a great idea to compare C# generics to C++ templates for various reasons - they're fundamentally two really quite different approaches to accomplishing similar things in some situations. The C++ approach is certainly flexible in some ways - although it doesn't allow (as I understand it) templates which only exist in binary form, or new template specializations to be created at execution time. Basically the C++ templating approach doesn't sit well with the rest of how .NET fits together.
Now as for why you can't specify some type arguments and allow others to be inferred (which is a language decision rather than a platform decision; I'm sure it would be feasible as far as .NET itself is concerned) - again, I believe this is for the sake of simplicity. Choosing the exact right method and the right type arguments is already extremely complicated in C# - more complicated than most C# developers can get their heads round. It involves:
Potentially considering methods up the type hierarchy from the compile-time type of the target
Overloading by number of parameters
Overloading by the number of type parameters
The effect of named arguments
The effect of optional parameters
The effect of generic type parameter constraints on parameter types (not constraints specified by the target method, note)
Method group to delegate conversions
Anonymous function conversions
Type inference for type arguments
Dynamic typing
Generic covariance and contravariance
Personally, I think that's enough to get my head around, without allowing yet more possiblities via "M can still be a candidate if it has at least as many type parameters as specified type arguments". Would you also want named type arguments and optional type parameters? ;)
I've looked at overloading quite a lot, following the spec thoroughly etc. I've found areas which make the language designers scratch their heads and try to work out what the compiler should do. I've found areas which the compiler definitely gets wrong. I wouldn't want to add any more complexity here without a really good reason.
So yes, it's basically for the sake of simplicity, and sometimes that's a pain - but often you can work around it. For every potential feature, you need to consider:
The benefit of the feature to end developers
The cost of the feature to end developers in terms of time spent understanding it
The cost to the language designers in designing and specifying it thoroughly
The cost to the compiler writers in implementing it correctly
The cost to the test team in testing it thoroughly (in conjunction with everything else around overloading)
The cost to future potential features (if this one makes the language more complicated, that leaves less "potentially grokable" additional complexity for other features)
As Dan said, C# doesn't allow you to infer only some type parameters of a generic parameter set. This is likely to enable overloading based on the number of generic parameters (which C# allows, at least for generic classes).
However, you can specify parameters of a generic class, and infer parameters of a generic method within that class. But this workaround isn't always a good solution.
One thing that can help in some cases where one would want to specify some type parameters and have others inferred is to create a generic static class with the parameters one wants to specify, and then within that class have a generic static method with the parameters one wants to have inferred. For example, I have a method which, given a method which is convertable to an Action(T,U,V), along with a T, will generate an Action(U,V) that will call that delegate with the originally-specified T along with the U and V. The method would be invoked as (vb syntax):
NewAction = ActionOf(Of FooType, BarType).NewAction(AddressOf MyFunctionOfBozFooBar, someBoz)
The compiler can determine one of the generic type parameters using the type of someBoz, even though it needs to have the FooType and BarType parameters explicitly specified.

Type erasure: Java vs C# [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C# vs Java generics
Java use Type erasure while C# keep type information at runtime, what are the practical difference in the behaviors of the language from this design?
There are a lot of issues with type erasure. It brings back bad memories. I haven't used Java since 1.6, so this may be out of date, but some things I remember:
You can't create a new T (or do anything that requires knowing what type T actually is)
Generic lists can't create an array of T
You can't use int, float, etc in generics with Java
This has performance and memory implications because you always have to use the heap versions (Integer, etc)
You can't implement a generic interface with two different Ts, e.g. class c implements IComparable<MyClass>, IComparable<MyOtherClass> is impossible.
More practically, you can't overload methods with different generic types, e.g. by taking in List<T1>, List<T2>, and so on. For example, Java -- How to deal with type erasure in constructors?
Everything is done by casting and boxing
Here's an example of something that's possible only if the type information is kept at runtime:
public string DoSomething<T>()
{
return typeof(T).Name;
}
The closest you could get in Java is something like:
public <T> string DoSomething(Class<T> theClass)
{
return theClass.getName();
}
Something that happens in Java due to type erasure is the creation of synthetic methods called "Bridge methods".
This usually happens when Java tries to compile a class or interface that extends a parameterized class, or implements a parameterized interface. In this case the Java compiler may need to create a synthetic method (bridge method) as part of the type-erasure process, which appears in the stack trace.
The compiler does this to preserve polymorphism of generic types after the type erasure process.
Java's documentation has an example.

Polymorphism, overloads and generics in C#

class Poly
{
public static void WriteVal(int i) { System.Console.Write("{0}\n", i); }
public static void WriteVal(string s) { System.Console.Write("{0}\n", s); }
}
class GenWriter<T>
{
public static void Write(T x) { Poly.WriteVal(x); }
}
Why the innocent (for C++ programmer) method Write is not acceptable in C#?
You can see that the compiler tries to match the parameter type T to concrete overloads before instantiation:
Error 3 The best overloaded method match for 'TestGenericPolyMorph.Poly.WriteVal(int)' has some invalid arguments
Of course. the purpose was not to use the static method as above, the intention is to create a wrapper with polymorphic behavior.
Note: I use VS 2010.
Please, note that all the needed information is available in compile time. Once again: the problem is that the validation is performed before the template instantiation.
Addition after the discussion:
Well, may be I have not stressed this out properly.
The question was not only about the difference between generics and templates, but also about solution of the following problem: given set of overloads addressing different types, I want to generate set of wrapper classes providing virtual method (polymorphism) for these types.
The price of resolution of virtual methods in run-time is minimal and does not hit performance. This is where C++ templates were handy. Obviously, the overhead of the run-time type resolution for dynamic is quite different.
So, the question is whether one can convert existing overloads to polymorphism without replication of the code and without paying the performance penalty (e.g., I am not sure what I gain with dynamic compared to "switch" attempting to cast except of nicer syntax).
One of the solutions I have seen so far was to generate/emit code (sic!), i.e. instead of cut-and-paste to do this automatically.
So, instead of the C++ template processing we simply do it manually or just re-invent macro/template processor.
Anything better?
Short answer:
C# generics are not C++ templates; despite their similar syntax they are quite different. Templates are built at compile time, once per instantiation, and the templatized code must be correct for only the template arguments actually provided. Templates do tasks like overload resolution and type analysis once per instantiation; they are basically a smart "search and replace" mechanism on source code text.
C# generics are truly generic types; they must be correct for any possible type argument. The generic code is analyzed once, overload resolution is done once, and so on.
Long answer: This is a duplicate of
What are the differences between Generics in C# and Java... and Templates in C++?
See the long answers there for details.
See also my article on the subject:
http://blogs.msdn.com/b/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx
Why can't you simply write:
public static void Write<T>(T x) { System.Console.Write("{0}\n", x); }
The C++ and C# generics are different ( http://msdn.microsoft.com/en-us/library/c6cyy67b(v=VS.80).aspx , search for "c# c++ generics difference" on your favorite search site)
Short: C# compiler must create complete GenWriter<T> class with all type matching by just looking at the class itself. So it does not know if T will only be int/string or any other type.
C++ compiler creates actual class by looking at instantiation of the generic GenWriter<int> and declaration GenWriter<T> and then creates class for that particular instance.
If someone was to call GenWriter(5.0), this would be inferred to GenWriter<double>(5.0), and the method call inside Write(T x) would become:
public static void Write(double x) { Poly.WriteVal(x); }
There is no overload of WriteVal which takes a double. The compiler is informing you that there are no valid overloads of WriteVal.
C# generics and C++ templates are not entirely equivalent.
You can't do that in C# because the compiler doesn't know what is the type of x in compile time.
Without knowledge of T's actual type, the compiler is concerned that you might have intended to perform a custom conversion. The simplest solution is to use the as operator, which is unamibigous because it cannot perform a custom conversion.
A more gereral solution is to cast to object first. This is helpfull because of boxing unboxing issues:
return (int)(object) x;
Have in mind that C# Generics are not like C++ templates. C++ templates are pieces of code that compile for each type separately. While C# generics are compiled in an assebmly.

Generics can't infer second parameter? [duplicate]

This question already has answers here:
Why must I provide explicitly generic parameter types While the compiler should infer the type?
(3 answers)
Closed 9 years ago.
I've noticed that the C# compiler doesn't infer second generic parameter.
Example:
C++ template code: (yea I know that templates don't work like generics)
class Test {
public:
template <class T,class V>
T test(V v) {
//do something with v
return T();
}
};
int i = 0;
Test t = new Test();
double j = t.test<double>(i); //infers V as int
The templates (and generics) can't infer return type, so in C++ I give it the first template parameter, and the second template parameter is inferred from the variable type.
Now, same example in C#:
class Test {
public T test<T,V>(V v) where T: new() {
//do something with v
return new T();
}
};
int i = 0;
Test t = new Test();
double j = t.test<double>(i); //Error Using the generic method 'Test.test<T,V>(V)' requires '2' type arguments
But if i use 1 type, I don't have to explicitly specify the type:
class Test {
public V test<V>(V v) where V: new() {
return new V();
}
};
int i = 0;
Test t = new Test();
int j = t.test(i); //OK infers V as int.
So, why can't C# generics infer the second type (while in c++ templates it clearly can) ?
I'm sure it's designed that way (I doubt they the .Net team overlooked this), so why is it designed this way that I must explicitly specify both types?
Edit:
From the discussions we had in the answers so far, both languages support overloading by number of template parameters.
So again, why is C# designed this way ? What's different in the language implementation that doesn't allow to explicitly declare only one parameter ?
C# has been designed to be a slightly less brain-bending language than C++.
In particular, I don't think it's a great idea to compare C# generics to C++ templates for various reasons - they're fundamentally two really quite different approaches to accomplishing similar things in some situations. The C++ approach is certainly flexible in some ways - although it doesn't allow (as I understand it) templates which only exist in binary form, or new template specializations to be created at execution time. Basically the C++ templating approach doesn't sit well with the rest of how .NET fits together.
Now as for why you can't specify some type arguments and allow others to be inferred (which is a language decision rather than a platform decision; I'm sure it would be feasible as far as .NET itself is concerned) - again, I believe this is for the sake of simplicity. Choosing the exact right method and the right type arguments is already extremely complicated in C# - more complicated than most C# developers can get their heads round. It involves:
Potentially considering methods up the type hierarchy from the compile-time type of the target
Overloading by number of parameters
Overloading by the number of type parameters
The effect of named arguments
The effect of optional parameters
The effect of generic type parameter constraints on parameter types (not constraints specified by the target method, note)
Method group to delegate conversions
Anonymous function conversions
Type inference for type arguments
Dynamic typing
Generic covariance and contravariance
Personally, I think that's enough to get my head around, without allowing yet more possiblities via "M can still be a candidate if it has at least as many type parameters as specified type arguments". Would you also want named type arguments and optional type parameters? ;)
I've looked at overloading quite a lot, following the spec thoroughly etc. I've found areas which make the language designers scratch their heads and try to work out what the compiler should do. I've found areas which the compiler definitely gets wrong. I wouldn't want to add any more complexity here without a really good reason.
So yes, it's basically for the sake of simplicity, and sometimes that's a pain - but often you can work around it. For every potential feature, you need to consider:
The benefit of the feature to end developers
The cost of the feature to end developers in terms of time spent understanding it
The cost to the language designers in designing and specifying it thoroughly
The cost to the compiler writers in implementing it correctly
The cost to the test team in testing it thoroughly (in conjunction with everything else around overloading)
The cost to future potential features (if this one makes the language more complicated, that leaves less "potentially grokable" additional complexity for other features)
As Dan said, C# doesn't allow you to infer only some type parameters of a generic parameter set. This is likely to enable overloading based on the number of generic parameters (which C# allows, at least for generic classes).
However, you can specify parameters of a generic class, and infer parameters of a generic method within that class. But this workaround isn't always a good solution.
One thing that can help in some cases where one would want to specify some type parameters and have others inferred is to create a generic static class with the parameters one wants to specify, and then within that class have a generic static method with the parameters one wants to have inferred. For example, I have a method which, given a method which is convertable to an Action(T,U,V), along with a T, will generate an Action(U,V) that will call that delegate with the originally-specified T along with the U and V. The method would be invoked as (vb syntax):
NewAction = ActionOf(Of FooType, BarType).NewAction(AddressOf MyFunctionOfBozFooBar, someBoz)
The compiler can determine one of the generic type parameters using the type of someBoz, even though it needs to have the FooType and BarType parameters explicitly specified.

C# generics compared to C++ templates [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
What are the differences between Generics in C# and Java… and Templates in C++?
What are the differences between C# generics compared to C++ templates? I understand that they do not solve exactly the same problem, so what are the pros and cons of both?
You can consider C++ templates to be an interpreted, functional programming language disguised as a generics system. If this doesn't scare you, it should :)
C# generics are very restricted; you can parameterize a class on a type or types, and use those types in methods. So, to take an example from MSDN, you could do:
public class Stack<T>
{
T[] m_Items;
public void Push(T item)
{...}
public T Pop()
{...}
}
And now you can declare a Stack<int> or Stack<SomeObject> and it'll store objects of that type, safely (ie, no worried about putting SomeOtherObject in by mistake).
Internally, the .NET runtime will specialize it into variants for fundamental types like int, and a variant for object types. This allows the representation for Stack<byte> to be much smaller than that of Stack<SomeObject>, for example.
C++ templates allow a similar use:
template<typename T>
class Stack
{
T *m_Items;
public void Push(const T &item)
{...}
public T Pop()
{...}
};
This looks similar at first glance, but there are a few important differences. First, instead of one variant for each fundamental type and one for all object types, there is one variant for each type it's instantiated against. That can be a lot of types!
The next major difference is (on most C++ compilers) it will be compiled in each translation unit it's used in. That can slow down compiles a lot.
Another interesting attribute to C++'s templates is they can by applied to things other than classes - and when they are, their arguments can be automatically detected. For example:
template<typename T>
T min(const T &a, const T &b) {
return a > b ? b : a;
}
The type T will be automatically determined by the context the function is used in.
These attributes can be used to good ends, at the expense of your sanity. Because a C++ template is recompiled for each type it's used against, and the implementation of a template is always available to the compiler, C++ can do very aggressive inlining on templates. Add to that the automatic detection of template values in functions, and you can make anonymous pseudo-functions in C++, using boost::lambda. Thus, an expression like:
_1 + _2 + _3
Produces an object with a seriously scary type, which has an operator() which adds up its arguments.
There are plenty of other dark corners of the C++ template system - it's an extremely powerful tool, but can be painful to think about, and sometimes hard to use - particularly when it gives you a twenty-page long error message. The C# system is much simpler - less powerful, but easier to understand and harder to abuse.
http://blogs.msdn.com/csharpfaq/archive/2004/03/12/88913.aspx
Roughly, much of the difference has to do with the fact that templates are resolved at compile-time, and generics are resolved at runtime.
Extensive answer on Stack Overflow: What are the differences between Generics in C# and Java... and Templates in C++?
This blog entry from Eric Gunnerson covers this topic quite well.
The biggest immediate difference is that templates are a compile time feature whereas generics are a runtime feature.
This looks like a handy reference.
http://msdn.microsoft.com/en-us/library/c6cyy67b.aspx

Categories