Polymorphism, overloads and generics in C# - 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.

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.

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

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.

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

Does the C# 4.0 "dynamic" keyword make Generics redundant?

I'm very excited about the dynamic features in C# (C#4 dynamic keyword - why not?), especially because in certain Library parts of my code I use a lot of reflection.
My question is twofold:
1. does "dynamic" replace Generics, as in the case below?
Generics method:
public static void Do_Something_If_Object_Not_Null<SomeType>(SomeType ObjToTest) {
//test object is not null, regardless of its Type
if (!EqualityComparer<SomeType>.Default.Equals(ObjToTest, default(SomeType))) {
//do something
}
}
dynamic method(??):
public static void Do_Something_If_Object_Not_Null(dynamic ObjToTest) {
//test object is not null, regardless of its Type?? but how?
if (ObjToTest != null) {
//do something
}
}
2. does "dynamic" now allow for methods to return Anonymous types, as in the case below?:
public static List<dynamic> ReturnAnonymousType() {
return MyDataContext.SomeEntities.Entity.Select(e => e.Property1, e.Property2).ToList();
}
cool, cheers
EDIT:
Having thought through my question a little more, and in light of the answers, I see I completely messed up the main generic/dynamic question. They are indeed completely different. So yeah, thanks for all the info.
What about point 2 though?
dynamic might simplify a limited number of reflection scenarios (where you know the member-name up front, but there is no interface) - in particular, it might help with generic operators (although other answers exist) - but other than the generic operators trick, there is little crossover with generics.
Generics allow you to know (at compile time) about the type you are working with - conversely, dynamic doesn't care about the type.
In particular - generics allow you to specify and prove a number of conditions about a type - i.e. it might implement some interface, or have a public parameterless constructor. dynamic doesn't help with either: it doesn't support interfaces, and worse than simply not caring about interfaces, it means that we can't even see explicit interface implementations with dynamic.
Additionally, dynamic is really a special case of object, so boxing comes into play, but with a vengence.
In reality, you should limit your use of dynamic to a few cases:
COM interop
DLR interop
maybe some light duck typing
maybe some generic operators
For all other cases, generics and regular C# are the way to go.
To answer your question. No.
Generics gives you "algorithm reuse" - you write code independent of a data Type. the dynamic keyword doesn't do anything related to this. I define List<T> and then i can use it for List of strings, ints, etc...
Type safety: The whole compile time checking debate. Dynamic variables will not alert you with compile time warnings/errors in case you make a mistake they will just blow up at runtime if the method you attempt to invoke is missing. Static vs Dynamic typing debate
Performance : Generics improves the performance for algorithms/code using Value types by a significant order of magnitude. It prevents the whole boxing-unboxing cycle that cost us pre-Generics. Dynamic doesn't do anything for this too.
What the dynamic keyword would give you is
simpler code (when you are interoperating with Excel lets say..) You don't need to specify the name of the classes or the object model. If you invoke the right methods, the runtime will take care of invoking that method if it exists in the object at that time. The compiler lets you get away even if the method is not defined. However it implies that this will be slower than making a compiler-verified/static-typed method call since the CLR would have to perform checks before making a dynamic var field/method invoke.
The dynamic variable can hold different types of objects at different points of time - You're not bound to a specific family or type of objects.
To answer your first question, generics are resolved compile time, dynamic types at runtime. So there is a definite difference in type safety and speed.
Dynamic classes and Generics are completely different concepts. With generics you define types at compile time. They don't change, they are not dynamic. You just put a "placeholder" to some class or method to make the calling code define the type.
Dynamic methods are defined at runtime. You don't have compile-time type safety there. The dynamic class is similar as if you have object references and call methods by its string names using reflection.
Answer to the second question: You can return anonymous types in C# 3.0. Cast the type to object, return it and use reflection to access it's members. The dynamic keyword is just syntactic sugar for that.

Categories