I am new to C# and was trying to write an SNTP server on the weekend.
During the course of this development I ended up with exactly the same question as this one: How to use generics to pass argument to a non-generic method?
The question, repeated here is: "How to use generics to pass argument to a non-generic method?" The crucial answer to this question was that the non-generic method in question didn't have an overload which accepted an Object.
Now the question I have is a follow on question: why is Generics implemented this way? Or to rephrase, why are constraints required at all?
My understanding so far is that generics help to preserve compile time type safety which means that the compiler knows what types are being dealt with at compile time.
Why wasn't C# (or perhaps this question should pertain to the CLR) implemented such that the compiler can accept the fact that a generic class/method is being created in which an argument can be provided which may not be acceptable in all cases. Then, when the generic class/method get's invoked, the compiler can see the issue and complain at that time.
Is this a technical limitation?
It just seems like a real pity that a generic method cannot be created to wrap a non generic method with multiple overloads. Unless I opt to defer type checking to run time which is the solution to the aforementioned question, I would have to wrap this overloaded method with a suite of methods, one for each signature, even though the code within it will look identical. This would have been an ideal place to leverage a generic method.
The person who can best explain this is Eric Lippert, and he did, in What’s the difference, part one: Generics are not templates:
We do the overload resolution once and bake in the result. We do not change it at runtime when someone, possibly in an entirely different assembly, uses string as a type argument to the method. The IL we’ve generated for the generic type already has the method its going to call picked out. The jitter does not say “well, I happen to know that if we asked the C# compiler to execute right now with this additional information then it would have picked a different overload. Let me rewrite the generated code to ignore the code that the C# compiler originally generated...” The jitter knows nothing about the rules of C#.
[...]
Now, if you do want overload resolution to be re-executed at runtime based on the runtime types of the arguments, we can do that for you; that’s what the new “dynamic” feature does in C# 4.0. Just replace “object” with “dynamic” and when you make a call involving that object, we’ll run the overload resolution algorithm at runtime and dynamically spit code that calls the method that the compiler would have picked, had it known all the runtime types at compile time.
So why not: because the runtime wouldn't know how to re-generate the required code.
And something about a design philosophy that your code should fail as early as possible, preferably during compile time, but I can't find that quote right now.
Microsoft.CSharp is required to use dynamic feature.
I understand there are binders, evaluators and helpers in the assembly.
But why it has to be language-specific?
Why Microsoft.CSharp and not Microsoft.Dynamic or System.Dynamic?
Please, explain.
Let's say we have d.x where d is dynamic.
C# compiler
1. applies C# language rules
2. gets "property or field access"
3. emits (figurally) Binder.GetPropertyOrField(d, "x")
Now, being asked to reference Microsoft.CSharp may make one think that language-agnostic binder can't handle this case, and C#-only something got its way through compilation and requires special library.
Compiler had a bad day?
To your first question, it is language-specific because it needs to be.
In C# you call a method with too many arguments and you get an error. In Javascript, the extra arguments are simply ignored. In C# you access a member that doesn't exist and get an error, while in Javascript you get undefined. Even if you discovered all these varying feature sets and put it all into System.Core, the next language fad of the month is sure to have some super neat feature that it wouldn't support. It's better to be flexible.
There is common code in .NET core, under the System.Dynamic and System.Runtime.CompilerServices namespaces. It just can't all be common.
And as for your second question, the need for the "special C# library" could of course be removed by transforming these language-specific behaviors inline, but why? That will needlessly bloat your IL code size. It is the same reasoning for you not writing your own Int32.Parse every time you need to read in a number.
One reason I can think of - Visual Basic.NET has had late binding in it from day one, primarily oriented around how it interoperates with COM IDispatch interfaces - so if they wanted a language agnostic binder, they'd have had to adopt the Visual Basic rules - which includes that member lookup only works with Public members.
Apparently, the C# designers didn't want to be so strict. You can call this class' DoStuff method from C# via a dynamic reference:
public class Class1
{
internal void DoStuff()
{
Console.WriteLine("Hello");
}
}
Whereas attempting to call the same via Visual Basic's Object results in a MissingMemberException at runtime.
So because the C# designers weren't the first to arrive at the late-binding party, they could either follow Visual Basic's lead or they could say "each language will have its own rules" - they went with the latter.
There is a well-known fact that C++ templates are turing-complete, CSS is turing-complete (!) and that the C# overload resolution is NP-hard (even without generics).
But is C# 4.0 (with co/contravariance, generics etc) compile-time turing complete?
Unlike templates in C++, generics in C# (and other .net lang) are a runtime generated feature. The compiler does do some checking as to verify the types use but, actual substitution happens at runtime. Same goes for Co and contravariance if I'm not mistaken as well as even the preprocessor directives. Lots of CLR magic.
(At the implementation level, the primary difference is that C#
generic type substitutions are performed at runtime and generic type
information is thereby preserved for instantiated objects)
See MSDN
http://msdn.microsoft.com/en-us/library/c6cyy67b(v=vs.110).aspx
Update:
The CLR does preform type checking via information stored in the metadata associated with the compiled assemblies(Vis-à-vis Jit Compliation), It does this as one of its many services,(ShuggyCoUk answer on this question explains it in detail) (others include memory management and exception handling). So with that I would infer that the compiler has a understanding of state as progression and state as in machine internal state (TC,in part, mean being able to review data (symbols) with so reference to previous data(symbols) , conditionally and evaluate) (I hesitated to state the exact def of TC as I, myself am not sure I have it fully grasped, so feel free to fill in the blanks and correct me when applicable ) So with that I would say with a bit of trepidation, yes, yes it can be.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I generally avoid casting types as much as possible since I am under the impression that it's poor coding practice and may incur a performance penalty.
But if someone asked me to explain why exactly that is, i would probably look at them like a deer in headlights.
So why/when is casting bad?
Is it general for java, c#, c++ or does every different runtime environment deal with it on it's own terms?
Specifics for a any language are welcome, example why is it bad in c++?
You've tagged this with three languages, and the answers are really quite different between the three. Discussion of C++ more or less implies discussion of C casts as well, and that gives (more or less) a fourth answer.
Since it's the one you didn't mention explicitly, I'll start with C. C casts have a number of problems. One is that they can do any of a number of different things. In some cases, the cast does nothing more than tell the compiler (in essence): "shut up, I know what I'm doing" -- i.e., it ensures that even when you do a conversion that could cause problems, the compiler won't warn you about those potential problems. Just for example, char a=(char)123456;. The exact result of this implementation defined (depends on the size and signedness of char), and except in rather strange situations, probably isn't useful. C casts also vary in whether they're something that happens only at compile time (i.e., you're just telling the compiler how to interpret/treat some data) or something that happens at run time (e.g., an actual conversion from double to long).
C++ attempts to deal with that to at least some extent by adding a number of "new" cast operators, each of which is restricted to only a subset of the capabilities of a C cast. This makes it more difficult to (for example) accidentally do a conversion you really didn't intend -- if you only intend to cast away constness on an object, you can use const_cast, and be sure that the only thing it can affect is whether an object is const, volatile, or not. Conversely, a static_cast is not allowed to affect whether an object is const or volatile. In short, you have most of the same types of capabilities, but they're categorized so one cast can generally only do one kind of conversion, where a single C-style cast can do two or three conversions in one operation. The primary exception is that you can use a dynamic_cast in place of a static_cast in at least some cases and despite being written as a dynamic_cast, it'll really end up as a static_cast. For example, you can use dynamic_cast to traverse up or down a class hierarchy -- but a cast "up" the hierarchy is always safe, so it can be done statically, while a cast "down" the hierarchy isn't necessarily safe so it's done dynamically.
Java and C# are much more similar to each other. In particular, with both of them casting is (virtually?) always a run-time operation. In terms of the C++ cast operators, it's usually closest to a dynamic_cast in terms of what's really done -- i.e., when you attempt to cast an object to some target type, the compiler inserts a run-time check to see whether that conversion is allowed, and throw an exception if it's not. The exact details (e.g., the name used for the "bad cast" exception) varies, but the basic principle remains mostly similar (though, if memory serves, Java does make casts applied to the few non-object types like int much closer to C casts -- but these types are used rarely enough that 1) I don't remember that for sure, and 2) even if it's true, it doesn't matter much anyway).
Looking at things more generally, the situation's pretty simple (at least IMO): a cast (obviously enough) means you're converting something from one type to another. When/if you do that, it raises the question "Why?" If you really want something to be a particular type, why didn't you define it to be that type to start with? That's not to say there's never a reason to do such a conversion, but anytime it happens, it should prompt the question of whether you could re-design the code so the correct type was used throughout. Even seemingly innocuous conversions (e.g., between integer and floating point) should be examined much more closely than is common. Despite their seeming similarity, integers should really be used for "counted" types of things and floating point for "measured" kinds of things. Ignoring the distinction is what leads to some of the crazy statements like "the average American family has 1.8 children." Even though we can all see how that happens, the fact is that no family has 1.8 children. They might have 1 or they might 2 or they might have more than that -- but never 1.8.
Lots of good answers here. Here's the way I look at it (from a C# perspective).
Casting usually means one of two things:
I know the runtime type of this expression but the compiler does not know it. Compiler, I am telling you, at runtime the object that corresponds to this expression is really going to be of this type. As of now, you know that this expression is to be treated as being of this type. Generate code that assumes that the object will be of the given type, or, throw an exception if I'm wrong.
Both the compiler and the developer know the runtime type of the expression. There is another value of a different type associated with the value that this expression will have at runtime. Generate code that produces the value of the desired type from the value of the given type; if you cannot do so, then throw an exception.
Notice that those are opposites. There are two kinds of casts! There are casts where you are giving a hint to the compiler about reality - hey, this thing of type object is actually of type Customer - and there are casts where you are telling the compiler to perform a mapping from one type to another - hey, I need the int that corresponds to this double.
Both kinds of casts are red flags. The first kind of cast raises the question "why exactly is it that the developer knows something that the compiler doesn't?" If you are in that situation then the better thing to do is usually to change the program so that the compiler does have a handle on reality. Then you don't need the cast; the analysis is done at compile time.
The second kind of cast raises the question "why isn't the operation being done in the target data type in the first place?" If you need a result in ints then why are you holding a double in the first place? Shouldn't you be holding an int?
Some additional thoughts here:
Link
Casting errors are always reported as run-time errors in java. Using generics or templating turns these errors into compile-time errors, making it much easier to detect when you have made a mistake.
As I said above. This isn't to say that all casting is bad. But if it is possible to avoid it, its best to do so.
Casting is not inherently bad, it's just that it's often misused as a means to achieve something that really should either not be done at all, or done more elegantly.
If it was universally bad, languages would not support it. Like any other language feature, it has its place.
My advice would be to focus on your primary language, and understand all its casts, and associated best practices. That should inform excursions into other languages.
The relevant C# docs are here.
There is a great summary on C++ options at a previous SO question here.
I'm mostly speaking for C++ here, but most of this probably applies to Java and C# as well:
C++ is a statically typed language. There are some leeways the language allows you in this (virtual functions, implicit conversions), but basically the compiler knows the type of every object at compile-time. The reason to use such a language is that errors can be caught at compile-time. If the compiler know the types of a and b, then it will catch you at compile-time when you do a=b where a is a complex number and b is a string.
Whenever you do explicit casting you tell the compiler to shut up, because you think you know better. In case you're wrong, you will usually only find out at run-time. And the problem with finding out at run-time is, that this might be at a customer's.
Java, c# and c++ are strongly typed languages, although strongly typed languages can be seen as inflexible, they have the benefit of doing type checking at compile time and protect you against runtime errors that are caused by having the wrong type for certain operations.
There are basicaly two kind of casts: a cast to a more general type or a cast to an other types (more specific). Casting to a more general type (casting to a parent type) will leave the compile time checks intact. But casting to other types (more specific types) will disable compile time type checking and will be replaced by the compiler by a runtime check. This means you have less certainty you’re compiled code will run correctly. It also has some negligible performance impact, due to the extra runtime type check (the Java API is full of casts!).
Some types of casting are so safe and efficient as to often not even be considered casting at all.
If you cast from a derived type to a base type, this is generally quite cheap (often - depending on language, implementation and other factors - it is zero-cost) and is safe.
If you cast from a simple type like an int to a wider type like a long int, then again it is often quite cheap (generally not much more expensive than assigning the same type as that cast to) and again is safe.
Other types are more fraught and/or more expensive. In most languages casting from a base type to a derived type is either cheap but has a high risk of severe error (in C++ if you static_cast from base to derived it will be cheap, but if the underlying value is not of the derived type the behaviour is undefined and can be very strange) or relatively expensive and with a risk of raising an exception (dynamic_cast in C++, explicit base-to-derived cast in C#, and so on). Boxing in Java and C# is another example of this, and an even greater expense (considering that they are changing more than just how the underlying values are treated).
Other types of cast can lose information (a long integer type to a short integer type).
These cases of risk (whether of exception or a more serious error) and of expense are all reasons to avoid casting.
A more conceptual, but perhaps more important, reason is that each case of casting is a case where your ability to reason about the correctness of your code is stymied: Each case is another place where something can go wrong, and the ways in which it can go wrong add to the complexity of deducing whether the system as a whole will go wrong. Even if the cast is provably safe each time, proving this is an extra part of the reasoning.
Finally, the heavy use of casts can indicate a failure to consider the object model well either in creating it, using it, or both: Casting back and forth between the same few types frequently is almost always a failure to consider the relationships between the types used. Here it's not so much that casts are bad, as they are a sign of something bad.
There is a growing tendency for programmers to cling to dogmatic rules about use of language features ("never use XXX!", "XXX considered harmful", etc), where XXX ranges from gotos to pointers to protected data members to singletons to passing objects by value.
Following such rules, in my experience, ensures two things: you will not be a terrible programmer, nor will you be a great programmer.
A much better approach is to dig down and uncover the kernel of truth behind these blanket prohibitions, and then use the features judiciously, with the understanding that there are many situations for which they're the best tool for the job.
"I generally avoid casting types as much as possible" is a good example of such an overgeneralized rule. Casts are essential in many common situations. Some examples:
When interoperating with third-party code (especially when that code is rife with typedefs). (Example: GLfloat <--> double <--> Real.)
Casting from a derived to base class pointer/reference: This is so common and natural that the compiler will do it implicitly. If making it explicit increases readability, the cast is a step forwards, not backwards!
Casting from a base to derived class pointer/reference: Also common, even in well-designed code. (Example: heterogeneous containers.)
Inside binary serialization/deserialization or other low-level code that needs access to the raw bytes of built-in types.
Any time when it's just plain more natural, convenient, and readable to use a different type. (Example: std::size_type --> int.)
There are certainly many situations where it's not appropriate to use a cast, and it's important to learn these as well; I won't go into too much detail since the answers above have done a good job pointing some of them out.
To elaborate on KDeveloper's answer, it's not inherently type-safe. With casting, there is no guarantee that what you are casting from and casting to will match, and if that occurs, you will get a runtime exception, which is always a bad thing.
With specific regards to C#, because it includes the is and as operators, you have the opportunity to (for the most part) make the determination as to whether or not a cast would succeed. Because of this, you should take the appropriate steps to determine whether or not the operation would succeed and proceed appropriately.
In case of C#, one needs to be more careful while casting because of boxing/unboxing overheads involved while dealing with value types.
Not sure if someone already mentioned this, but in C# casting can be used in a rather safe manner, and is often necessary. Suppose you receive an object which can be of several types. Using the is keyword you can first confirm that the object is indeed of the type you are about to cast it to, and then cast the object to that type directly. (I didn't work with Java much but I'm sure there's a very straightforward way of doing it there as well).
You only cast an object to some type, if 2 conditions are met:
you know it is of that type
the compiler doesn't
This means not all the information you have is well represented in the type structure you use. This is bad, because your implementation should semantically comprise your model, which it clearly doesn't in this case.
Now when you do a cast, then this can have 2 different reasons:
You did a bad job in expressing the type relationships.
the languages type system simply is not expressive enough to phrase them.
In most languages you run into the 2nd situation a lot of times. Generics as in Java help a bit, the C++ template system even more, but it is hard to master and even then some things may be impossible or just not worth the effort.
So you could say, a cast is a dirty hack to circumvent your problems to express some specific type relationship in some specific language. Dirty hacks should be avoided. But you can never live without them.
Generally templates (or generics) are more type safe than casts. In that respect, i would say that an issue with casting is type-safety. However, there is another more subtle issue associated especially with downcasting: design. From my perspective at least, downcasting is a code smell, an indication that something might be wrong with my desing and i should investigate further. Why is simple: if you "get" the abstractions right, you simply don't need it! Nice question by the way...
Cheers!
To be really concise, a good reason is because of portability. Different architecture that both accommodate the same language might have, say, different sized ints. So if I migrate from ArchA to ArchB, which has a narrower int, I might see odd behavior at best, and seg faulting at worst.
(I'm clearly ignoring architecture independent bytecode and IL.)
This question already has answers here:
What are the differences between Generics in C# and Java... and Templates in C++? [closed]
(13 answers)
Closed 9 years ago.
I have heard that the Java implementation of Generics is not as good as the C# implementation. In that the syntax looks similar, what is it that is substandard about the Java implementation, or is it a religious point of view?
streloksi's link does a great job of breaking down the differences. The quick and dirty summary though is ...
In terms of syntax and usage. The syntax is roughly the same between the languages. A few quirks here and there (most notably in constraints). But basically if you can read one, you can likely read/use the other.
The biggest difference though is in the implementation.
Java uses the notion of type erasure to implement generics. In short the underlying compiled classes are not actually generic. They compile down to Object and casts. In effect Java generics are a compile time artifact and can easily be subverted at runtime.
C# on the other hand, by virtue of the CLR, implement generics all they way down to the byte code. The CLR took several breaking changes in order to support generics in 2.0. The benefits are performance improvements, deep type safety verification and reflection.
Again the provided link has a much more in depth breakdown I encourage you to read
The difference comes down to a design decision by Microsoft and Sun.
Generics in Java is implemented through type erasure by the compiler, which means that the type checking occurs at compile time, and the type information is removed. This approach was taken to keep the legacy code compatible with new code using generics:
From The Java Tutorials, Generics: Type Erasure:
When a generic type is instantiated,
the compiler translates those types by
a technique called type erasure — a
process where the compiler removes all
information related to type parameters
and type arguments within a class or
method. Type erasure enables Java
applications that use generics to
maintain binary compatibility with
Java libraries and applications that
were created before generics.
However, with generics in C# (.NET), there is no type erasure by the compiler, and the type checks are performed during runtime. This has its benefits that the type information is preserved in the compiled code.
From Wikipedia:
This design choice is leveraged to
provide additional functionality, such
as allowing reflection with
preservation of generic types, as well
as alleviating some of the limitations
of erasure (such as being unable to
create generic arrays). This
also means that there is no
performance hit from runtime casts and
normally expensive boxing conversions.
Rather than saying ".NET generics is better than Java generics", one should look into the difference in the approach to implement generics. In Java, it appears that preserving compatibility was a high priority, while in .NET (when introduced at version 2.0), the realizing the full benefit of using generics was a higher priority.
Also found this conversation with Anders Hejlsberg that may be interesting too. To summarize points that Anders Hejlsberg made with some additional notes: Java generics were made for maximum compatibility with existing JVM that led to few odd things versus implementation you see in C#:
Type erasure forces implementation to represent every generic parametrized value as Object. While compiler provides automatic casts between Object and more specific type, it does not remove the negative impact of the type casts and boxing on performance (e.g. Object is cast to specific type MyClass or int had to be boxed in Integer, which would be even more serious for C#/.NET if they followed type erasure approach due to user-defined value types). As Anders said: "you don't get any of the execution efficiency" (that reified generics enable in C#)
Type erasure makes information available at compile time not accessible during runtime. Something that used to be List<Integer> becomes just a List with no way to recover generic type parameter at runtime. This makes difficult to build reflection or dynamic code-generation scenarios around Java generics. More recent SO answer shows a way around it via anonymous classes. But without tricks, something like generating code at runtime via reflection that gets elements from one collection instance and puts it to another collection instance can fail at runtime during execution of dynamically generated code: reflection doesn't help with catching mismatch in List<Double> versus List<Integer> in these situations.
But +1 for the answer linking to Jonathan Pryor's blog post.